SGU 121 Bridges painting(构造)

49 篇文章 0 订阅

Description
给出一个n个顶点的有向图(无重边),现要给每条边染色1或2,问是否存在一种染色方案使得每个顶点所连的边中两种颜色都有(如果某点度数小于2则不考虑)
Input
第一行为一整数n表示点数,之后n行每行表示一个点的邻接表,以0结束每行的输入
Output
如果存在一个合法的染色方案,则按输入顺序输出每条边应该染的颜色,否则输出No solution
Sample Input
6
2 3 0
1 3 0
1 2 5 0
5 0
4 6 3 0
5 0
Sample Output
1 2 0
1 2 0
2 2 1 0
2 0
2 2 1 0
2 0
Solution
考虑顶点的度数
如果一个点是奇度顶点(只考虑度数不小于2的,因为小于2的顶点不会影响染色方案的存在),那么从这个点开始dfs交叉染色会出现两种情况:第一种情况是经过一条环后回到该点,此时这个环除该点外一定全部满足条件了(染色是交叉的),而该点就算不满足条件,由于其是奇度顶点且度数不小于2,则必然可以从与该点相连的另一条边开始染另一种颜色使得该点满足条件;第二种情况是没有环,同样的,下一次可以从与这个奇度顶点相连的另一条边开始染另一种颜色。故奇度顶点一定可以满足条件。
如果一个点是偶度顶点,同样的,从这个点开始染色会有和奇度顶点一样的两种情况,其中第二种情况可以满足条件,即从这个偶度顶点开始染色如果不成环则可以从与这个偶度顶点相连的另一条边开始染另一种颜色;但是如果成环且成的是奇环且这个顶点的度数是2,这个偶度顶点就不满足条件。
通过上面的分析可以看出,首先从奇度顶点开始染色更优,因为这样不仅可以让奇度顶点满足条件而且并不会影响偶度顶点的染色
Code

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
#define maxn 111
vector<int>g[maxn];
int n,degree[maxn],mark[maxn][2],ans[maxn][maxn];
void init()
{
    for(int i=1;i<=n;i++)g[i].clear();
    memset(degree,0,sizeof(degree));
    memset(mark,0,sizeof(mark));
    memset(ans,-1,sizeof(ans));
}
void dfs(int u,int cur)
{
    cur^=1;
    for(int i=0;i<degree[u];i++)
        if(ans[u][g[u][i]]==-1)
        {
            ans[u][g[u][i]]=ans[g[u][i]][u]=cur;
            mark[u][cur]=mark[g[u][i]][cur]=1;
            dfs(g[u][i],cur);
            cur^=1;
        }
}
int main()
{
    while(~scanf("%d",&n))
    {
        init();
        for(int i=1;i<=n;i++)
        {
            int temp;
            while(scanf("%d",&temp),temp)
                g[i].push_back(temp),degree[temp]++;
        }
        for(int i=1;i<=n;i++)
            if(degree[i]&1)dfs(i,0);
        for(int i=1;i<=n;i++)dfs(i,0);
        int flag=1;
        for(int i=1;i<=n;i++)
            if((!mark[i][0]||!mark[i][1])&&degree[i]>1)
            {
                flag=0;
                break; 
            }
        if(flag)
            for(int i=1;i<=n;i++)
            {
                for(int j=0;j<g[i].size();j++)
                    printf("%d ",ans[i][g[i][j]]+1);
                printf("0\n");
            }
        else printf("No solution\n");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值