CodeForces-1217D (拓扑排序/dfs 判环)

题意

https://vjudge.net/problem/CodeForces-1217D

请给一个有向图着色,使得没有一个环只有一个颜色,您需要最小化使用颜色的数量。

思路

因为是有向图,每个环两个颜色就可以满足了。所以最大为2,最小为1。

法1 dfs:

用dfs判断有向图的环,每次把构成环的最后那条边染成2,其余染成1。

法2 拓扑排序:

容易发现,对于一个有向图,如果成环那么点的序号必不是单调的,因为最后的那个点又会连回起始点。

所以我们把u<v染成1,u>v染成2,然后拓扑排序判环,如果有环那么就输出染色方案,否则全输出1。

代码

法1:

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
const int N=5e3+5;
const int mod=1e9+7;
const double eps=1e-8;
const double PI = acos(-1.0);
#define lowbit(x) (x&(-x))
vector<int> g[N];
int e[N][N],vis[N],col[N],gg,in[N];
void dfs(int u)
{
    int sz=g[u].size();
    in[u]=1;
    for(int i=0;i<sz;i++)
    {
        int v=g[u][i];
        if(!vis[v])
        {
            vis[v]=1;
            col[e[u][v]]=1;
            dfs(v);
        }
        else if(in[v])
        {
            col[e[u][v]]=2;
            gg=1;
        }
        else
        {
            col[e[u][v]]=1;
        }
    }
    in[u]=0;
}
int main()
{
    std::ios::sync_with_stdio(false);
    int n,m;
    while(cin>>n>>m)
    {
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=m;i++)
        {
            int u,v;
            cin>>u>>v;
            g[u].push_back(v);
            e[u][v]=i;
        }
        gg=0;
        for(int i=1;i<=n;i++)
        {
            if(!vis[i])
            {
             //   col[i]=1;
                vis[i]=1;
                dfs(i);
            }
        }
        if(!gg)
        {
            cout<<1<<endl;
            for(int i=1;i<=m;i++)
                cout<<1<<" ";
            cout<<endl;
        }
        else
        {
            cout<<2<<endl;
            for(int i=1;i<=m;i++)
                cout<<col[i]<<" ";
            cout<<endl;
        }
    }
    return 0;
}

  

法2:

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
const int N=200005;
const int mod=1e9+7;
const double eps=1e-8;
const double PI = acos(-1.0);
#define lowbit(x) (x&(-x))
vector<int> g[N];
int col[N],du[N];
int n,m;
bool topo()
{
    queue<int> q;
    for(int i=1; i<=n; i++)
        if(du[i]==0) q.push(i);
    int cnt=0;
    while(!q.empty())
    {
        int t=q.front();
        for(int i:g[t])
        {
            du[i]--;
            if(du[i]==0)
                q.push(i);
        }
        cnt++;
        q.pop();
    }
    if(cnt!=n)
        return false;
    return true;
}
int main()
{
    std::ios::sync_with_stdio(false);
    cin>>n>>m;
    for(int i=1; i<=m; i++)
    {
        int u,v;
        cin>>u>>v;
        g[u].push_back(v);
        col[i]=(u<v);
        du[v]++;
    }
    if(topo())
    {
        cout<<1<<endl;
        for(int i=1;i<=m;i++)
            cout<<1<<" ";
        cout<<endl;
    }
    else
    {
        cout<<2<<endl;
        for(int i=1;i<=m;i++)
            cout<<col[i]+1<<" ";
        cout<<endl;
    }
    return 0;
}

  

posted @ 2019-12-04 16:13  MCQ1999  阅读(406)  评论(0编辑  收藏  举报