题意:让你找一条权值最小的割边,如果该图本身就有孤立的连通块或点就直接输出0;
分析:很裸的边双连通问题,直接敲代码,只是有个很坑的地方:当求出的割边权值为0时,输出1,因为需要派遣一个人去放炸药。
附代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 1050;
struct Node{
int v,next,w;
}e[maxn*maxn];
int Map[maxn][maxn];
int head[maxn],num,scc,index,dfn[maxn],top,low[maxn],sta[maxn],id[maxn];
void add(int a,int b,int c){
e[num].v=b;
e[num].w=c;
e[num].next=head[a];
head[a]=num++;
}
void init()
{
memset(head,-1,sizeof(head));
//memset(vis,0,sizeof(vis));
//en = 0;
top = 0;
scc=num = index=0;memset(dfn,0,sizeof(dfn));
}
void tarjan(int u,int fa)
{
dfn[u] = low[u] = ++index;
sta[++top] = u;
int cnt=0;
for(int i = head[u]; i != -1; i = e[i].next)
{
int v = e[i].v;
if(!dfn[v])
{
tarjan(v,u);
low[u] = min(low[u],low[v]);
}
else if (fa==v)
{
if (cnt) low[u] = min(low[u],dfn[v]);//重边
cnt++;
//可以改成continue;没有重边的时候
}
else low[u] = min(low[u],dfn[v]);
}
if(dfn[u]==low[u])
{
int x;
scc++;
// printf("~~~~%d\n",scc);
do
{
x = sta[top--];
id[x] = scc;
// printf("%d ",x);
}while(x!=u);
// printf("\n");
}
}
int main(){
int n,m;
while(scanf("%d %d",&n,&m) && (n+m)){
init();
memset(Map,INF,sizeof(Map));
while(m--){
int a,b,c;
scanf("%d %d %d",&a,&b,&c);
add(a,b,c);
add(b,a,c);
}
int sum=0;
for(int i=1;i<=n;i++){
if(!dfn[i]){
tarjan(i,-1);
sum++;
}
}
int Min=INF;
/*for(int i=1;i<=n;i++){
printf("~~~~%d\n",id[i]);
}*/
if(sum>1){
printf("0\n");
continue;
}
else{
for(int i=1;i<=n;i++){
for(int j=head[i];j!=-1;j=e[j].next){
int v=e[j].v;
if(id[i]!=id[v]){
Min=min(Min,e[j].w);
}
}
}
}
if(Min>=INF){
puts("-1");
}
else{
if(Min==0) puts("1");
else
printf("%d\n",Min);
}
}
}