codeforces794D dfs+图上hash

http://codeforces.com/problemset/problem/794/D

题意:在一个国家有 n 座城市和一些双向边。这些城市被编号为 1 到 n。 一共有 m 条双线边,第 i条边连接城市 ui 和 vi。保证任意两个城市是连通的。

每个城市都有一个标签,第 i 个城市的标签为 xi。对于任意一对点 (u, v) ,如果这对点满足 |xu - xv| ≤ 1 则一定有一条边,否则一定没有。

现在我们想知道是否存在这样一种合法的标签方式。

显而易见的可以看出一个结论,就是如果一个点连出去的三个边互不连通,就是不可行的

不怎么显而易见甚至需要看一下题解才能发现的第二个结论,就是如果一个点和他连到的点组成的集合与另一个点和他连到的点组成的集合完全相同的话,一定存在一种标签方法使得他们的标签相同

因为这样可以使得这两个点对除了这两个点之外的点的限制最小。

将所有这样的点缩点之后,原本的图就变成了一条链,我们采用直接染色的方法去检查就可以了

对于第二个结论,产生的点集合,可以用图上的Hash来解决,奥妙重重。

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)  
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))  
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x);  
#define Pri(x) printf("%d
", x)
#define Prl(x) printf("%lld
",x);  
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long  
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second 
typedef vector<int> VI;
const double eps = 1e-9;
const int maxn = 3e5 + 10;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7; 
int N,M,K;
struct Edge{
    int to,next;
}edge[maxn * 2];
int head[maxn],tot;
ULL Hash[maxn];
ULL id[maxn];
int color[maxn];
bool vis[maxn],use[maxn * 2];
void init(){
    Mem(head,-1);
    tot = 0;
}
void add(int u,int v){
    edge[tot].next = head[u];
    edge[tot].to = v;
    head[u] = tot++;
}
void dfs(int x){
    vis[x] = 1;
    for(int i = head[x]; ~i; i = edge[i].next){
        int v = edge[i].to;
        if(Hash[v] == Hash[x]) color[v] = color[x];
    }
    for(int i = head[x]; ~i; i = edge[i].next){
        int v = edge[i].to;
        if(!vis[v]){
            if(!color[v]){
                for(int j = color[x] - 1; j <= color[x] + 1; j ++){
                    if(!use[j]){
                        color[v] = j;
                        use[j] = 1;
                        break;
                    }
                }
            }
            dfs(v);
        }
    }
}
int main()
{
    Sca2(N,M); init(); id[0] = 1;
    For(i,1,N) Hash[i] = id[i] = id[i - 1] * 3;
    For(i,1,M){
        int u,v; Sca2(u,v);
        add(u,v); add(v,u);
        Hash[u] += id[v]; Hash[v] += id[u];
    }
    color[1] = 3e5 + 1; use[color[1]] = 1; vis[1] = 1;
    dfs(1);
    For(i,1,N) if(!color[i]){puts("NO");return 0;}
    puts("YES");
    For(i,1,N) printf("%d ",color[i]);
    #ifdef VSCode
    system("pause");
    #endif
    return 0;
}
原文地址:https://www.cnblogs.com/Hugh-Locke/p/9746722.html