交通灯 并查集

  

Problem Description

相信交通灯对于你来说并不陌生,交通灯分为红色和绿色两个阶段,这两个阶段互相更替,保障着道路的安全。

在杭州一共有n个路口,编号依次为1到n。这些路口之间连接着m条双向道路,每条道路连接着两个不同的路口,且任意两个路口之间最多连接着一条道路。每条道路中央都设置着一个交通灯。

为了保障道路的安全,对于任意两条道路,如果它们连接了同一个路口,那么它们不能同色。

你的朋友正乘着飞机从杭州的上空飞过,并拍了一张杭州的照片。在照片里,每条道路的交通灯的颜色都清晰可辨。

你并不知道你的朋友是在什么时候按下的快门,于是你想统计出有多少种可能的方案。每个方案可以用一个颜色序列col1,col2,…,colm(coli∈{′Red′,′Green′})来描述,表示每个交通灯的颜色。

Input

第一行包含一个正整数T(1≤T≤5000),表示测试数据的组数。

每组数据第一行包含两个正整数n,m(1≤n,m≤100000),表示路口和道路的数量。

接下来m行,每行包含两个正整数ui,vi(1≤ui,vi≤n,ui≠vi),表示一条连接ui路口和vi路口的道路,任意两个路口之间最多连接着一条道路。

输入数据保证所有数据中n和m的总和都不超过1000000。

Output

对于每组数据输出一行一个整数,即ans,即可能的方案数对1000000007=109+7取模的结果。

注意城市布局可能不能保障道路的安全,此时的答案应该为0。

Sample Input

2
3 3
1 2
2 3
3 1
4 2
1 2
3 4

Sample Output

0
4

比赛的时候拿到这题感觉是可以做的一开始想到 最大匹配  但是好像不行然后开并查集  要求求出联通块个数cnt  然后2的cnt次幂就是答案( 比赛的时候居然写成2*cnt了  不知道错到哪里去了QAQ )题意还要求我们判环 如果是奇数环则不行  偶数环是可以的  如正方形和三角形

比赛的时候我在并查集里面加了cnt 以此来判环  这种想法是对的  因为一个点如果有三条边显然是错的   除去这种情况  剩下的就是一个点小于等于两条边 那么只能构成一条链或者一个环  比赛的时候几乎写出来了  但是最后答案的形式弄错饿了(2*cnt)

其实很多情况不需要什么算法  直接乱搞就行了补题的时候很快就想到思路  用一个vis就可以表示两种灯的状态了

过程中还是wa了一些细节1.爆int了    开ll  并且只要是乘法 只管加mod就行了!!!2.如果是0个联通块 不应该是2的0次方  而是0

一定要等思路完善了再开始敲  不然只是浪费时间  并且只想沿着错误的思路思考  难以放弃并且重新开启新的思路

比赛的思路:

#include<bits/stdc++.h>
using namespace std;
//input
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);i--)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m);
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s);
#define ll long long
#define inf 0x3f3f3f3f
#define REP(i,N)  for(int i=0;i<(N);i++)
#define CLR(A,v)  memset(A,v,sizeof A)
//////////////////////////////////
#define N 500+5
#define mod 1000000007
int vis[100005];
int cnt[100005];
int f[100005];
int find1(int x)
{
    return x==f[x]?x:f[x]=find1(f[x]);
}
void union1(int a,int b)
{
    int x=find1(a);
    int y=find1(b);
    if(x!=y)
    f[x]=y,cnt[y]+=cnt[x];
}
ll fastpow(ll x,int n)
{
    ll ans=1;
    while(n)
    {
        if(n&1)
            ans*=x,ans%=mod;
        x*=x,x%=mod;//疯狂加mod就完事了
     n>>=1;
    }
    return ans%mod;
}
int main()
{
    int cas;
    RI(cas);
    while(cas--)
    {
        int n,m;RII(n,m);
        rep(i,1,n)
        f[i]=i,vis[i]=0,cnt[i]=1;
        int ok=1;
        while(m--)
        {
            int a,b;RII(a,b);
            if(!ok)continue;
            vis[a]++;
            vis[b]++;
            if(vis[a]>2||vis[b]>2)ok=0;
            int x=find1(a),y=find1(b);
            if(x!=y)
                union1(a,b);
            else
            {
                if(cnt[x]%2==1)ok=0;//如果为奇数环 则无法实现
                else
                union1(a,b);
            }
        }
        if(!ok)printf("0\n");
        else
        {
            ll cnt=0;
            rep(i,1,n)
            if(f[i]==i&&vis[i])
            cnt++;
            if(cnt==0)printf("0\n");
            else printf("%lld\n",fastpow(2,cnt));
        }
    }
    return 0;
}

模拟输入路径写法:

#include<bits/stdc++.h>
using namespace std;
//input
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);i--)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m);
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s);
#define ll long long
#define inf 0x3f3f3f3f
#define REP(i,N)  for(int i=0;i<(N);i++)
#define CLR(A,v)  memset(A,v,sizeof A)
//////////////////////////////////
#define N 500+5
#define mod 1000000007
int vis[100005][2];
int f[100005];
int find1(int x)
{
    return x==f[x]?x:f[x]=find1(f[x]);
}
ll fastpow(ll x,int n)
{
    ll ans=1;
    while(n)
    {
        if(n&1)
            ans*=x,ans%=mod;
        x*=x,x%=mod;//疯狂加mod就完事了
     n>>=1;
    }
    return ans%mod;
}
int main()
{
    int cas;
    RI(cas);
    while(cas--)
    {
        int n,m;
        RII(n,m);
        rep(i,1,n)f[i]=i,vis[i][0]=vis[i][1]=0;
        int ok=1;
        while(m--)
        {
            int a,b;
            RII(a,b);
            if(!ok)continue;
            if(!vis[a][0]&&!vis[b][0])
                vis[a][0]=vis[b][0]=1,f[ find1(a) ]=find1(b);
            else if(!vis[a][1]&&!vis[b][1])
                vis[a][1]=vis[b][1]=1,f[ find1(a) ]=find1(b);
            else
                ok=0;
        }
        if(!ok)printf("0\n");
        else
        {
            ll cnt=0;
            rep(i,1,n)
            if(f[i]==i&&( vis[i][0]||vis[i][1]) )//如果是孤立的点而不是路则不能给路染色
                cnt++;

            if(cnt==0)
                printf("0\n");
            else
            printf("%lld\n",fastpow( 2,cnt ));
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/bxd123/p/10658413.html

时间: 2024-07-30 05:50:20

交通灯 并查集的相关文章

八中教室的灯加强版 【并查集】

本人水平有限,题解不到为处,请多多谅解 本蒟蒻谢谢大家观看 题目: 八中教室的灯加强版 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 79  Solved: 38[Submit][Status][Web Board] Description 八中一共有被用M条双向道路连接的N个教室(1<=N,M<=3000).为了关闭整个八中,master wen 计划每一次关闭掉一个教室.当一个教室被关闭了,所有的连接到这个教室的道路都会被关闭,而且再也不能够

并查集问题hdu 1232

Problem Description 某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇.省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可).问最少还需要建设多少条道路? Input 测试输入包含若干测试用例.每个测试用例的第1行给出两个正整数,分别是城镇数目N ( < 1000 )和道路数目M:随后的M行对应M条道路,每行给出一对正整数,分别是该条道路直接连通的两个城镇的编号.为简单起见,城镇从1

并查集详解 (转)

http://blog.csdn.net/dellaserss/article/details/7724401 我从CSDN转的文章,原文作者我也不懂是谁,文章写得真的是诙谐幽默,使得内容更容易理解了. 来看一个实例,杭电OJ 1232畅通工程 Problem Description 某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇.省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可).问最少还需要建

hdu 1232 畅通工程(并查集算法)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1232 畅通工程 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 31088    Accepted Submission(s): 16354 Problem Description 某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条

并查集/生成树问题 | 问题集合

写在前面 似乎没什么可以写的? 那还是扯一下吧. 题目大部分带题号没给特殊地址/链接的都是洛谷的题 然后亲戚和朋友两道题库被我刷烂的题我就不搬进来了(:懒 P1536 村村通 题目描述 某市调查城镇交通状况,得到现有城镇道路统计表.表中列出了每条道路直接连通的城镇.市政府"村村通工程"的目标是使全市任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要相互之间可达即可).请你计算出最少还需要建设多少条道路? 输入格式: 每个输入文件包含若干组测试测试数据,每组测试数据的第一行给出

HDU 1232 畅通工程 (并查集)

某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇.省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可).问最少还需要建设多少条道路? Input测试输入包含若干测试用例.每个测试用例的第1行给出两个正整数,分别是城镇数目N ( < 1000 )和道路数目M:随后的M行对应M条道路,每行给出一对正整数,分别是该条道路直接连通的两个城镇的编号.为简单起见,城镇从1到N编号. 注意:两个城市之间可以有多条道

bzoj 1196: [HNOI2006]公路修建问题 二分+并查集

题目链接 1196: [HNOI2006]公路修建问题 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1576  Solved: 909[Submit][Status][Discuss] Description OI island是一个非常漂亮的岛屿,自开发以来,到这儿来旅游的人很多.然而,由于该岛屿刚刚开发不久,所以那里的交通情况还是很糟糕.所以,OIER Association组织成立了,旨在建立OI island的交通系统. OI isla

hdu 1233 还是畅通工程 kruskal最小生成树并查集实现

http://acm.hdu.edu.cn/showproblem.php?pid=1233 杭电ACM暑期集训队的选拔 还是畅通工程 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 30319    Accepted Submission(s): 13542 Problem Description 某省调查乡村交通状况,得到的统计表中列

HDU 1232:畅通问题(并查集)

畅通工程 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 29362    Accepted Submission(s): 15452 Problem Description 某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇.省政府"畅通工程"的目标是使全省任何两个城镇间都可以实现交通(但不一定有