NEUACM1132: Renew MST Quickly 增量最小生成树

来源:互联网 发布:淘宝网中老年大码棉袄 编辑:程序博客网 时间:2024/04/28 19:58

题目链接:http://acm.neu.edu.cn/hustoj/problem.php?id=1132

题目描述

  You are given a connected undirected graphy which contains n vertices and n-1 edges.  Each edge has a weight value. Now, you are asked to answer q similar questions. In each question, you are told a new edge which connects u and v (two different vertices). Of course, this new edge has a weight value w too. You  need to tell us the minimizest total weight value of the spanning tree(which is connected and acyclic and only contains n-1 edges) of the new graphy which contains n-1 orignal edges and a new edge. 

输入

The input file has several test cases. 
   In each test case, the first line contains an integer n (It means n vertices and they are numbered from 1 to n) and each of the following n-1 lines contains three integers x,y and w. It means there is an edge between x and y and its weight is w.
   Then it has an integer q in the following. In the following q questions, each one contains three integers u,v and k.(It means the new edge is connected between vertice u and vand its weight is k.)  
   Note: 2<=n<=1000 , 1<=w,k<=100  , u!=v , x!=y, 1<=q<=1000000   

输出

   In each test case, please print out a line "Test #t". t is the number of the test case. In the following, it has q lines which contain the anwser of the question.

先给出N个点和N-1条边,而后对于每个查询,在图中加入一条的边,权值为W,问加入这条边之后最小生成树权值。
如果对于每个查询运行一次最小生成树算法,对于高达100000个查询,无异于自杀行为。。。那么能不能通过某种预操作,对于每个查询在O(1)时间内输出答案呢?
当在最小生成树中加入一条边e=(u,v)后,图中恰好包含一个环,根据回路性质(假定所有边权值均不相同。设C是图G中的任意回路,边e是C上权值最大的边,则图G的所有生成树均不包含e),删除该回路上的权值最大的边即可。因此思路就清晰了,先通过预操作,找出maxcost[u][v]即(u,v)路径上的最大权值,对于每个查询(u,v,w),只需比较maxcost[u][v]与w的大小关系。
#include <iostream>#include <cstdio>#include <string.h>#define MAXN 1050#define INF 40000000using namespace std; struct EdgeNode{     int to,next,w;}edge[2*MAXN];int head[MAXN],dis[MAXN][MAXN];int cnt,n,m; void add_edge(int u,int v,int w){      edge[cnt].to=v,edge[cnt].next=head[u];      edge[cnt].w=w,head[u]=cnt++;} void dfs(int s,int v,int la,int curmax,int w){      curmax=max(curmax,w);      dis[s][v]=dis[v][s]=curmax;      for(int i=head[v];i!=-1;i=edge[i].next)      {            int vi=edge[i].to;            if(vi!=la)                dfs(s,vi,v,curmax,edge[i].w);      }} int main(){    int t=1,u,v,w,sum;    while(scanf("%d",&n)!=EOF)    {          cnt=0,sum=0;          memset(head,-1,sizeof(head));          for(int i=0;i<n-1;i++)          {                 scanf("%d%d%d",&u,&v,&w);                 sum+=w;                 add_edge(u,v,w);                 add_edge(v,u,w);          }          for(int i=1;i<=n;i++)            dfs(i,i,0,-1,0);         printf("Test #%d\n",t++);          scanf("%d",&m);          while(m--)          {               scanf("%d%d%d",&u,&v,&w);               if(w>=dis[u][v])                   printf("%d\n",sum);                else                   printf("%d\n",sum-dis[u][v]+w);          }    }    return 0;} /**************************************************************    Problem: 1132    Language: C++    Result: 正确    Time:727 ms    Memory:5604 kb****************************************************************/




0 0