HDOJ 4005-The war解题报告

链接:http://acm.hdu.edu.cn/showproblem.php?pid=4005

题意是说,在一个无向带权图中可以在原来没有直接相连的两个点上加一条边,然后要求你删去一条边,要求得出无论对方加的是哪一条边,你都可以删除一条<=v的边导致这个图不连通,要找出最小的V是多少。

分析:首先,对于图中的双连通分量来说,删除其中的边是没有任何意义的,所以先进行缩点

View Code
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #define N 20005
  5 #define M 200005
  6 #define inf 0x7fffffff
  7 using namespace std;
  8 int head[N],head1[N],cnt,cnt1,dp[N];
  9 struct node
 10 {
 11     int u,v,next,w;
 12 };
 13 node e[2*M],e1[2*M];
 14 int Ti[N],ti,low[N],bel[N];
 15 bool used[N],flag;
 16 int cnt2,stk[N],top,insta[N];
 17 int ans,a,b;
 18 int min(int a,int b)
 19 {
 20     return a<b?a:b;
 21 }
 22 void init()
 23 {
 24     memset(head,-1,sizeof(head));
 25     memset(head1,-1,sizeof(head1));
 26     memset(used,0,sizeof(used));
 27     memset(low,0,sizeof(low));
 28     memset(bel,0,sizeof(bel));
 29     memset(Ti,0,sizeof(Ti));
 30     memset(insta,0,sizeof(insta));
 31     cnt=cnt1=ti=top=cnt2=0;
 32 }
 33 void add(int u,int v,int w)
 34 {
 35     e[cnt].u=u;e[cnt].v=v;e[cnt].w=w;e[cnt].next=head[u];
 36     head[u]=cnt++;
 37     e[cnt].u=v;e[cnt].v=u;e[cnt].w=w;e[cnt].next=head[v];
 38     head[v]=cnt++;
 39 }
 40 void add1(int u,int v,int w)
 41 {
 42     e1[cnt1].u=u,e1[cnt1].v=v,e1[cnt1].w=w,e1[cnt1].next=head1[u];
 43     head1[u]=cnt1++;
 44 }
 45 void tarjan(int u,int rt)
 46 {
 47     Ti[u]=low[u]=++ti;
 48     stk[++top]=u;
 49     insta[u]=true;
 50     int i,j,v;
 51     for(i=head[u];i>=0;i=e[i].next)
 52     {
 53         v=e[i].v;
 54         if(v==rt)
 55         continue;
 56         if(!Ti[v])
 57         {
 58             tarjan(v,u);
 59             low[u]=min(low[u],low[v]);
 60         }
 61         else if(insta[v])
 62         low[u]=min(low[u],Ti[v]);
 63     }
 64     if(Ti[u]==low[u])
 65     {
 66         cnt2++;
 67         do
 68         {
 69             j=stk[top--];
 70             bel[j]=cnt2;
 71             insta[j]=false;
 72         }while(u!=j);
 73     }
 74 }
 75 void dfs(int u)
 76 {
 77     int v,i,j;
 78     used[u]=true;
 79     for(i=head1[u];i>=0;i=e1[i].next)
 80     {
 81         v=e1[i].v;
 82         if(used[v])
 83         continue;
 84         dfs(v);
 85         dp[v]=min(dp[v],e1[i].w);
 86         if(dp[u]>dp[v])
 87         {
 88             ans=min(dp[u],ans);
 89             dp[u]=dp[v];
 90         }
 91         else
 92         ans=min(ans,dp[v]);
 93     }
 94 }
 95 void creat(int n)
 96 {
 97     int i,j,u,v;
 98     for(i=1;i<=n;i++)
 99     if(!Ti[i])
100     tarjan(i,-1);
101     int minn=inf;
102     if(cnt2==1)
103     {
104         flag=false;
105         return;
106     }
107     for(i=0;i<cnt;i++)
108     {
109         if(bel[e[i].u]!=bel[e[i].v])
110         {
111             add1(bel[e[i].u],bel[e[i].v],e[i].w);
112             if(e[i].w<minn)
113             {
114                 minn=e[i].w;
115                 a=bel[e[i].u];
116                 b=bel[e[i].v];
117             }
118         }
119     }
120 }
121 int main()
122 {
123     int n,m,i,j,u,v,w;
124     while(scanf("%d%d",&n,&m)!=EOF)
125     {
126         init();
127         while(m--)
128         {
129             scanf("%d%d%d",&u,&v,&w);
130             add(u,v,w);
131         }
132         flag=true;
133         creat(n);
134         if(!flag)
135         {
136             printf("-1\n");
137             continue;
138         }
139         for(i=0;i<=n;i++)
140         dp[i]=inf;
141         ans=inf;
142         used[a]=used[b]=true;
143         dfs(a);
144         dfs(b);
145         if(ans==inf)
146         printf("-1\n");
147         else
148         printf("%d\n",ans);
149     }
150     return 0;
151 }

 

posted @ 2012-09-04 16:46  zhenhai  阅读(202)  评论(0编辑  收藏  举报