HDU Caocao's Bridges 题解

题目传送门

题目大意: 给出一张图,每条边上有若干个守卫,你能破坏掉一条边当且仅当你派出的人数不小于守卫数,然后这些人会干死守卫然后埋下炸弹将边炸毁。现在问要将图变得不连通至少要多少个人。

题解

如果本来就不连通,那么半个人都不用,直接输出 0 0

如果本来连通,那么显然我们要炸图中的桥(即割边)才行,那么我们只需要找出图中边权最小的桥即可。

然后,你会发现你得到了 WA 的好成绩。

这题的坑点还真是牛逼:桥的守卫数可以为 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);
    }
}
发布了234 篇原创文章 · 获赞 100 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/a_forever_dream/article/details/103041853