codeforces1394B Boboniu Walks on Graph

https://codeforces.com/contest/1394/problem/B

我们知道对于C的任意一组选择,最后每个点都只有一个出度,然而这题要保证最后所有点可以走到自己,那么这等价于每个点都只有一个出度和一个入度。

然后我们枚举每条边(u,v,l),把{out[u],rank(l)}给v,表示如果最后选择为c[out[u]]=rank(l),那么v这个点将会多一个入度,显然对于一个点v,所有这些选择之间必须选择一个,但不能选择多个,因为必须保证入度为1,所以他们是互斥了,用一个set表示每一个c[i]=j与哪些c[i2]=j2互斥

然后dfs的时候边选择边把当前选择互斥的那些点标记上,而且还要记录一下每个选择可以让多少点入度为1,要保证所有点都能入度为1.

#include
#define pb push_back
using namespace std;
typedef long long ll;

const int maxl=3e5+10;

int n,m,cas,k,cnt,tot,ans;
int a[maxl],out[maxl],c[maxl];
struct ed{int u,v,l;};
vector e[maxl];
ll in[100][100];int num[100][100];
typedef pair p;
set 

s[10][10]; vector

b[maxl]; inline bool cmp(const ed &a,const ed &b) { return a.lk) { if(res==0) ans++; return; } if(c[x]>0) { if(!in[x][c[x]]) { a[x]=c[x]; for(p d:s[x][c[x]]) ++in[d.first][d.second]; dfs(x+1,res-num[x][c[x]]); a[x]=0; for(p d:s[x][c[x]]) --in[d.first][d.second]; } } else { for(int i=1;i<=x;i++) if(!in[x][i]) { a[x]=i; for(p d:s[x][i]) ++in[d.first][d.second]; dfs(x+1,res-num[x][i]); for(p d:s[x][i]) --in[d.first][d.second]; a[x]=0; } } } inline void mainwork() { int u,v,l;ans=0; for(int i=1;i<=n;i++) { l=b[i].size(); if(l==0) return; else if(l==1) { u=b[i][0].first;num[u][b[i][0].second]++; if(c[u]==0) c[b[i][0].first]=b[i][0].second; else if(c[u]!=b[i][0].second) return; } else { sort(b[i].begin(),b[i].end()); for(int j=0;j1 && b[i][j]==b[i][j-1]) in[b[i][j].first][b[i][j].second]++; b[i].erase(unique(b[i].begin(),b[i].end()),b[i].end()); l=b[i].size(); for(int j=0;j

 

你可能感兴趣的:(dfs)