hdu4738:http://acm.hdu.edu.cn/showproblem.php?pid=4738
题意:抽象出来就是求一条边权最小的割边。
题解:直接用tarjan即可破。但是如果只注重这里你就错了,就是边权为0 的桥也要一个人去炸。
1 #pragma comment(linker,"/STACK:100000000,100000000")//阔栈的语句 2 #include <stdio.h> 3 #include <string.h> 4 #include <vector> 5 #define pb push_back 6 using namespace std; 7 const int maxn = 200002; 8 const int maxm = 1000002; 9 struct EDGE{ 10 int next, to, vis,w; 11 }edge[maxm*2];//记录边,vis表示这一条边是否被访问 12 struct GEEDGE { 13 int u, to; 14 }geedge[maxm];//记录割边 15 int n,m,time,top,w,type,getot,cnt;//time是时间戳,type标记连通块,getot割边的数量,cnt边数 16 int head[maxn],st[maxn],dfn[maxn],low[maxn],belo[maxn];//belo[i],表示i属于哪个连通块 17 int start,ans1,ans,u,v,tval[maxn]; 18 void init(){ 19 time=top=type=getot=cnt=0; 20 memset(head,-1,sizeof(head)); 21 memset(dfn,0,sizeof(dfn)); 22 memset(low,0,sizeof(low)); 23 memset(belo,0,sizeof(belo)); 24 } 25 void add(int u,int v,int w){ 26 edge[cnt].to=v; 27 edge[cnt].next=head[u]; 28 edge[cnt].vis=0; 29 edge[cnt].w=w; 30 head[u]=cnt++; 31 } 32 void dfs(int u) {//可以处理重边的情况 33 low[u] = dfn[u] = ++time; 34 st[++top] = u; 35 for(int i = head[u];i != -1;i = edge[i].next) { 36 if(edge[i].vis) continue; 37 edge[i].vis = edge[i^1].vis = 1; 38 int to = edge[i].to; 39 if(!dfn[to]) { 40 dfs(to); 41 low[u] = min(low[u], low[to]); 42 if(low[to] > dfn[u]) {//表示找到一个连通块 43 type++; 44 int v; 45 do { 46 v = st[top--]; 47 belo[v] = type;//表示v属于第type个连通块 48 } while(v != to); 49 geedge[++getot].u = u;//记录割边的起点 50 geedge[getot].to = to;//记录割边的另一个点 51 tval[getot]=edge[i].w; 52 } 53 } 54 else 55 low[u] = min(low[u], low[to]); 56 } 57 } 58 int main(){ 59 while(~scanf("%d%d",&n,&m)&&n){ 60 init(); 61 for(int i=1;i<=m;i++){ 62 scanf("%d%d %d",&u,&v,&w); 63 add(u,v,w); 64 add(v,u,w); 65 } 66 dfs(1);bool flag=false; 67 for(int i=1;i<=n;i++){ 68 if(!dfn[i]){ 69 flag=true; 70 break; 71 } 72 } 73 ans1=getot;ans=100000000; 74 for(int i=1;i<=ans1;i++){ 75 ans=min(ans,tval[i]); 76 } 77 if(ans==0)ans=1; 78 if(flag)ans=0; 79 if(!ans1&&!flag)printf("-1 "); 80 else 81 printf("%d ",ans); 82 } 83 }