hdu 4738 Caocao's Bridges 求无向图的桥【Tarjan】

<题目链接>

题目大意:

  曹操在长江上建立了一些点,点之间有一些边连着。如果这些点构成的无向图变成了连通图,那么曹操就无敌了。周瑜为了防止曹操变得无敌,就打算去摧毁连接曹操的点的桥。但是诸葛亮把所有炸弹都带走了,只留下一枚给周瑜。所以周瑜只能炸一条桥。

  题目给出n,m。表示有n个点,m条桥。

  接下来的m行每行给出a,b,c,表示a点和b点之间有一条桥,而且曹操派了c个人去守卫这条桥。

  现在问周瑜最少派多少人去炸桥。

  如果无法使曹操的点成为多个连通图,则输出-1.

解题思路:

  就是用Tarjan找出图中所有的桥,并且不断更新所有桥上防守人数最少的值。

需要注意几点:

  1.首先先判断整张图是否为连通图,如果不为连通图,则无需派人去炸桥;

  2.如果原图不存在桥,即,只炸毁一条边不能够破坏原图的连通性,就直接输出-1;

  3.如果防守人数最少的那个桥上的防守人数为0,也需要派人去炸桥,因为那座桥不会自动毁坏。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<cstdlib>
 6 using namespace std;
 7 const int maxn = 1007;
 8 const int INF = 0x3f3f3f3f;
 9 struct node{
10     int to,cost,next;
11 };
12 node edge[maxn*maxn];
13 int head[maxn],n,m,num,ans,sum,dfn[maxn],child,low[maxn];
14 void addedge(int u,int v,int c){    //双向存图
15     edge[num].to=v;edge[num].cost=c;edge[num].next=head[u];
16     head[u]=num++;
17     edge[num].to=u;edge[num].cost=c;edge[num].next=head[v];
18     head[v]=num++;
19 }
20 void tarjan(int u,int fa){
21     child++;     //child记录连通到的点的数量
22     low[u]=dfn[u]=sum++;
23     for(int i=head[u];i!=-1;i=edge[i].next){
24         int v=edge[i].to;
25         if(i==(fa^1)) continue;    //标记反向边 
26         if(!dfn[v]){
27             tarjan(v,i);
28             low[u]=min(low[u],low[v]);
29             if(dfn[u]<low[v]){    //桥的判定方法  因为low[v]<dfn[u],说明v和u不属于同一联通块,并且v不能通过u-v之间的边到达比low[v]小的点,说明这条边为桥
30                 ans=min(ans,edge[i].cost);    //更新权值最小的桥
31             }
32         }
33         else low[u]=min(low[u],dfn[v]);
34     }
35 }
36 
37 int main(){
38     int a,b,c;
39     while(~scanf("%d%d",&n,&m),n||m){
40         memset(head,-1,sizeof(head));
41         memset(dfn,0,sizeof(dfn));
42         memset(low,0,sizeof(low));
43         ans=INF;child=0;sum=1;
44         for(int i=1;i<=m;i++){
45             scanf("%d%d%d",&a,&b,&c);
46             addedge(a,b,c);      
47         }
48         tarjan(1,-1);
49         if(child<n) printf("0\n");    //如果原图本来就不是连通图,就直接输出0即可
50         else if(ans==INF)printf("-1\n"); //如果没有桥,即,只派出一个人不能将原图的连通性破坏,就直接输出-1
51         else if(ans==0) printf("1\n");   //如果桥上无人防守,也需要派人去把那座桥炸毁   
52         else printf("%d\n",ans);
53     }
54     return 0;
55 }

 

 

2018-08-17

posted @ 2018-08-17 00:03  悠悠呦~  阅读(208)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end