ZOJ - 2588 求桥

渡轮王国是一个不错的小国,位于N个岛屿上,由M座桥梁连接。所有的桥梁都非常漂亮,深受王国每个人的喜爱。当然,桥梁系统的设计方式使得人们可以从任何岛屿到达任何其他岛屿。

但最近,这个王国遭遇了巨大的悲痛。渡轮王国被伟大的战士乔丹的军队征服,他决定烧毁所有连接岛屿的桥梁。这是一个非常残酷的决定,但约旦的巫师们建议他不要这样做,因为在那之后他自己的军队将无法从一个岛屿到另一个岛屿。所以乔丹决定尽可能多地烧掉桥梁,这样他的军队仍然可以从任何一个岛屿到达任何一个岛屿。

现在,渡轮王国的穷人想知道桥梁会被烧毁。当然,他们无法了解这一点,因为要烧毁的桥梁清单保密。然而,一位老人说你可以帮助他们找到一组肯定不会被烧毁的桥梁。

所以他们来找你并寻求帮助。你能做到吗?

输入

输入包含多个测试用例。输入的第一行是单个整数T(1 <= T <= 20),它是测试用例的数量。随后是T个测试用例,每个测试用例前面都有一个空白行。

每个案例的第一行包含N和M--分别是渡轮王国中的岛屿和桥梁数量(2 <= N <= 10 000,1 <= M <= 100 000)。接下来的M行每行包含两个不同的整数,并描述桥。请注意,一对岛屿之间可能存在多个桥梁。

产量

在每个案例的第一行打印K - 肯定不会被烧毁的桥梁数量。在第二行打印K整数 - 这些桥的数量。桥从一开始编号,因为它们在输入中给出。

连续两个案例应该用一个空行分隔。在最后一个测试用例之后不应该生成空白行。

样本输入

2 

6 7 
1 2 
2 3 
2 4 
5 4 
1 3 
4 5 
3 6 

10 16 
2 6 
3 7 
6 5 
5 9 
5 4 
1 2 
9 8 
6 4 
2 10 
3 8 
7 9 
1 4 
2 4 
10 5 
1 6 
6 10

样本输出

2 
3 7 

1 
4

分析:就是求图的桥

#include<bits/stdc++.h>
#include<cstdio>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<cmath>
#include<vector>
#include<cstring>
#include<string>
#include<iostream>
#include<iomanip>
#define mset(a,b)   memset(a,b,sizeof(a))
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int mod=100000007;
const int N=505050;
const int inf=0x3f3f3f3f;
//priority_queue<int,vector<int>,greater<int> >q;
#include <iostream>
#include<vector>
#include<stack>
#include<queue>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int N=20000;
int n,m;
int low[N],dfn[N],head[N*10];
int sum,bridge,k;int tot;
int uu[N*10];int p;
struct node
{
    int v,w,next,id;
}s[N*10];
void init()
{
    tot=bridge=k=0;p=0;
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    memset(s,0,sizeof(s));
    memset(uu,0,sizeof(uu));
    memset(head,-1,sizeof(head));
}
void add(int u,int v,int c)
{
    s[tot].v=v;
    s[tot].id=c;
    s[tot].next=head[u];
    head[u]=tot++;
}
void Trajan(int u,int fa)
{
    low[u]=dfn[u]=++k;
    int flag=0;
    for(int i=head[u];~i;i=s[i].next)
    {
        int v=s[i].v;
        if(v==fa&&!flag)//重边
        {
            flag++;
            continue;
        }
        if(!dfn[v])
        {
            Trajan(v,u);
            low[u]=min(low[u],low[v]);
            if(low[v]>dfn[u])//求桥
            {
                bridge++;
                uu[p++]=s[i].id;
            }
        }
        else
            low[u]=min(low[u],dfn[v]);
    }
}
int main()
{
   // freopen("in.txt","r",stdin);
    int t,u,v;
    scanf("%d",&t);
    while(t--)
    {
        init();
        scanf("%d%d",&n,&m);
        for(int i=1; i<=m; i++)
        {
            scanf("%d%d",&u,&v);
            add(u,v,i);
            add(v,u,i);
        }
        Trajan(1,-1);
        printf("%d\n",bridge);
        if(bridge)
        {
            sort(uu,uu+bridge);
            for(int i=0; i<bridge-1; i++)
            {
                printf("%d ",uu[i]);
            }
            printf("%d\n",uu[bridge-1]);
        }
        if(t)puts("");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Kuguotao/article/details/88594132
ZOJ