安全网络

作者在 2010-12-30 00:19:34 发布以下内容
Description
  现在有个一个内部局域网络,里面有N台机器。为了某种安全原因的考虑,有些机器之间是无法直接通讯的,即使可以通讯,机器与机器之间的通讯都是经过加密的。由于不同机器之间传输的内容不同,所以他们通讯采用的加密级别也不大相同。不同的加密级别导致破解的难度不一样,越高的加密级别破解需要的时间也越多。如果我们获得了编号为i的机器的完全控制权,且机器i和机器j可以直接通讯,另外我们破解了机器i和机器j之间的加密信息,那么我们就得到了机器j的完全控制权。
  现在你通过了某种手段入侵了1号机器,得到了这台机器的完全控制权,为了扩大劳动果实,你准备对其余的机器也在你的控制当中,但是由于需要破解加密信息才能控制其它机器,你又不想浪费太多时间在破解上,现在你来算算你至少需要多少时间才能完全控制整个网络。
Input
  输入的第一行是两个正整数N(2 <= N <= 100,000) M(0 < M <= 200,000),表示机器的数目和允许通讯的机器对数。
  输入的第二行开始到第M+1行,每行3个整数,A B T( 1 <= A, B <= N, T <= 10,000, A ≠ B),表示机器A和机器B之间可以互相通讯,且破解这个通讯的时间是T。输入保证不存在重复的AB对。
Output
  输出完全控制所有机器的最少时间。如果无法满足要求则输出-1。
Sample Input
4 4
1 2 4
1 3 9
2 3 2
4 3 1
Sample Output
7
由于n=100,000,O(n2)的算法必定超时,我们知道当图为稀疏图时,最小生成树的Kruskal O(mlogm)算法,比传统的Prim()要快的多;
在实现Kruskal算法是,涉及到并查集的两个操作,Find( ), Union( ),应该都很了解了,具体的实现中用到 路径压缩和按秩合并 以提高运行效率;
源程序:
#include <iostream>
using namespace std;
struct Node{
       int rank;
       struct Node *p;
};
struct Edge{
       int u;
       int v;
       int len;
};
Edge edge[200001];
Node node[100001];
int n,m;

Node *Find(Node *xp)       //查找节点所属的集合,用到路径压缩
{
    Node *yp=xp;
    Node *zp=xp;
    Node *wp;
    while(yp->p!=NULL)
      yp=yp->p;
    while(zp->p!=NULL)
    {
      wp=zp->p;
      zp->p=yp;
      zp=wp;
    }
    return yp;
}
void Union(Node *up, Node *vp)    //合并两个集合,用到按帙合并
{
    if(up->rank>=vp->rank)
    {
       vp->p=up;
       if(up->rank==vp->rank)
         up->rank++;
    }
    else
    {
       up->p=vp;
    }
}

void swap(Edge &edge1, Edge &edge2)
{
    Edge tmp=edge1;
    edge1=edge2;
    edge2=tmp;
}
int partion(int p, int q)
{
    int t=rand()%(q-p+1)+p;
    swap(edge[t],edge[p]);
    int i=p;
    int j=q+1;
    while(true)
    {
      while(edge[++i].len<edge[p].len);
      while(edge[--j].len>edge[p].len);
      if(i>=j)break;
      swap(edge[i],edge[j]);
    }
    swap(edge[p],edge[j]);
    return j;
}
void quicksort(int p, int q)
{
    if(p<q)
    {
      int r=partion(p,q);
      quicksort(p,r-1);
      quicksort(r+1,q);
    }
}
void Kruskal()
{
    int i,c,len;
    Node *uFind,*vFind;
    quicksort(1,m);
    c=len=0;
    for(i=1;i<=m;i++)
    {
      uFind=Find(&node[edge[i].u]);
      vFind=Find(&node[edge[i].v]);
      if(uFind!=vFind)
      {
         c++;
         len+=edge[i].len;
         if(c==n-1)
         {
           printf("%d\n",len);
           return;
         }
         Union(uFind,vFind);
      }
    }
    printf("-1\n");     //网络不连通
}
int main()
{
    int i;
    scanf("%d%d",&n,&m);
    for(i=1;i<=m;i++)
    scanf("%d%d%d",&edge[i].u, &edge[i].v, &edge[i].len);
     Kruskal();
    return 0;
}
程序 | 阅读 1482 次
文章评论,共0条
游客请输入验证码
浏览29754次