思路:找边权值最小的桥,注意当为0时,至少要派一个人。
自己扩充了一下,找桥和割点,练习一下。
#include<iostream>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<cmath>
#include<climits>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
typedef long long LL;
using namespace std;
const int MAX_N=1010;
const int MAX_M=1000010;
const int INF=120000000;
struct node
{
int v,next,w;
} edge[MAX_M];
int N,M;
int dfn[MAX_N],low[MAX_N],pre[MAX_N],belong[MAX_N],sta[MAX_N];
int num,cnt,e,top,ans,ans1;
void init()
{
memset(pre,-1,sizeof(pre));
memset(dfn,0,sizeof(dfn));
num=cnt=e=top=ans=ans1=0;
}
void add_edge(int a,int b,int w)
{
edge[e].v=b;
edge[e].next=pre[a];
edge[e].w=w;
pre[a]=e++;
edge[e].v=a;
edge[e].next=pre[b];
edge[e].w=w;
pre[b]=e++;
}
void tarjan(int u,int fa)
{
dfn[u]=low[u]=++num;
sta[++top]=u;
int biao=0;
for(int j=pre[u]; j!=-1; j=edge[j].next)
{
int v=edge[j].v;
if(!dfn[v])
{
tarjan(v,u);
if(low[v]==dfn[v]||dfn[u]<low[v])//计算桥的个数
ans++;
if(low[v]>=dfn[u])//计算个割点的个数
ans1++;
low[u]=min(low[v],low[u]);
}
else if(fa==v)
{
if(biao)
low[u]=min(low[u],dfn[v]);
biao++;
}
else
low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u])
{
int j;
cnt++;
do
{
j=sta[top--];
belong[j]=cnt;
}
while(j!=u);
}
}
int main()
{
//freopen("in.txt","r",stdin);
int a,b,f;
while(cin>>N>>M,N+M)
{
init();
for(int i=0; i<M; i++)
{
cin>>a>>b>>f;
add_edge(a,b,f);
}
int sum=0;
for(int i=1; i<=N; i++)
{
if(!dfn[i])
{
tarjan(i,-1);
sum++;
}
}
cout<<"桥的个数:"<<ans<<endl;
cout<<"割点的个数:"<<ans1<<endl;
int Min=INF;
if(sum>1)//要是不联通,sum大于1
{
cout<<0<<endl;
continue;
}
else
for(int i=1; i<=N; i++) //找桥
{
for(int j=pre[i]; j!=-1; j=edge[j].next)
{
int v=edge[j].v;
if(belong[i]!=belong[v])
Min=min(Min,edge[j].w);
}
}
if(Min>=INF)
{
cout<<-1<<endl;
//continue;
}
else
{
if(Min==0)
cout<<1<<endl;
else
cout<<Min<<endl;
}
}
return 0;
}