题目大意: 给出一张图,每条边上有若干个守卫,你能破坏掉一条边当且仅当你派出的人数不小于守卫数,然后这些人会干死守卫然后埋下炸弹将边炸毁。现在问要将图变得不连通至少要多少个人。
题解
如果本来就不连通,那么半个人都不用,直接输出 0 0 0。
如果本来连通,那么显然我们要炸图中的桥(即割边)才行,那么我们只需要找出图中边权最小的桥即可。
然后,你会发现你得到了 WA 的好成绩。
这题的坑点还真是牛逼:桥的守卫数可以为 0 0 0,但是你埋炸弹至少要有一个人去埋……
所以代码如下:
#include <cstdio>
#include <cstring>
#define maxn 1010
int n,m;
struct edge{int y,z,next;};
edge e[(maxn*maxn)<<1];
int first[maxn],len,ans,cnt;
void buildroad(int x,int y,int z)
{
e[++len]=(edge){y,z,first[x]};
first[x]=len;
}
int dfn[maxn],low[maxn],id;
void dfs(int x,int from)
{
dfn[x]=low[x]=++id;
for(int i=first[x];i;i=e[i].next)
{
if(i==(from^1))continue;
int y=e[i].y;
if(!dfn[y])
{
dfs(y,i);
if(low[y]<low[x])low[x]=low[y];
if(low[y]>dfn[x]&&e[i].z<ans)ans=e[i].z;
}
else if(dfn[y]<low[x])low[x]=dfn[y];
}
}
inline int max(int x,int y){return x>y?x:y;}
int main()
{
while(scanf("%d %d",&n,&m),!(n==0&&m==0))
{
memset(first,0,sizeof(first));len=1;
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));id=0;
for(int i=1,x,y,z;i<=m;i++)
scanf("%d %d %d",&x,&y,&z),buildroad(x,y,z),buildroad(y,x,z);
ans=999999999,cnt=0;
for(int i=1;i<=n;i++)
if(!dfn[i])dfs(i,-1),cnt++;
if(n==1||cnt>1)ans=0;
else ans=max(ans,1);
if(ans==999999999)printf("-1\n");
else printf("%d\n",ans);
}
}