HDU 4738 Caocao's Bridges taijan (求割边,神坑)

神坑题。这题的坑点有1.判断连通,2.有重边,3.至少要有一个人背炸药

因为有重边,tarjan的时候不能用子结点和父节点来判断是不是树边的二次访问,所以我的采用用前向星存边编号的奇偶性关系,用^1来判断是不是树边

#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxe = 1000005<<1; const int maxv = 1005; int clock; int dfn[maxv],low[maxv],ecnt; int head[maxv],nxt[maxe],to[maxe],wei[maxe]; void init() { clock = ecnt = 0; memset(head,-1,sizeof(head)); memset(dfn,0,sizeof(dfn)); } void addEdge(int u,int v,int w) { to[ecnt] = v; wei[ecnt] = w; nxt[ecnt] = head[u]; head[u] = ecnt++; } int ans; void tarjan(int u,int fa) { dfn[u] = low[u] = ++clock; for(int i = head[u]; ~i ; i = nxt[i]){ int v = to[i]; if(i == (fa^1)) continue; if(!dfn[v]){ tarjan(v,i); low[u] = min(low[u],low[v]); if(low[v] > dfn[u]){ ans = min(ans,wei[i]); } }else { low[u] = min(low[u],dfn[v]); } } } int sum; bool vis[maxv]; void dfs(int u){ if(vis[u]) return; sum++; vis[u] = 1; for(int i = head[u]; ~i ; i = nxt[i]){ dfs(to[i]); } } const int INF = 1e9; int main() { int N,M; while(~scanf("%d%d",&N,&M)&&N){ init(); for(int i = 0; i < M; i++){ int U,V,W; scanf("%d%d%d",&U,&V,&W); addEdge(U,V,W); addEdge(V,U,W); } memset(vis,0,sizeof(vis)); sum = 0; dfs(1); if(sum < N) { printf("0\n"); continue; } ans = INF; tarjan(1,-1); if(ans == INF) { printf("-1\n"); continue; } ans = max(ans,1); printf("%d\n",ans); } return 0; }

 

你可能感兴趣的:(bridge)