6.24 冲刺国赛模拟 24
T2 简单图论题
原题:Gym-104053C Customs Controls 2
构造题。
这个限制可以进一步加强到对于每个节点 \(u\),\(1\to u\) 的路径权值都相等,定义为 \(d_u\)。
于是对 \(u\) 连边的两个节点的 \(d\) 一定相等,进而可以把所有相等的缩到一起,且这些点直接不能连边(点权至少是 \(1\)),这样可以对处理过后的图跑最长路,如果存在环一定无解。
最后的答案就是任意找一条连向 \(v\) 的边 \((u,v)\),其中 \(w_v=d_v-d_u\)。
点击查看代码
int t;
int n,m;
vector<int> E1[maxn],E2[maxn],E3[maxn];
int bel[maxn],id[maxn];
int find(int x){
if(x==bel[x]) return x;
return bel[x]=find(bel[x]);
}
int deg[maxn];
int f[maxn],g[maxn],cnt;
int main(){
freopen("dag.in","r",stdin);
freopen("dag.out","w",stdout);
t=read();
while(t--){
n=read(),m=read();
for(int i=1;i<=n;++i) E1[i].clear(),E2[i].clear(),E3[i].clear();
for(int i=1;i<=m;++i){
int u=read(),v=read();
E1[u].push_back(v),E2[v].push_back(u);
}
for(int i=1;i<=n;++i) bel[i]=i,id[i]=0,deg[i]=0;
for(int u=1;u<=n;++u){
for(int i=1;i<(int)E2[u].size();++i){
int v1=E2[u][i-1],v2=E2[u][i];
int f1=find(v1),f2=find(v2);
// printf("%d %d %d %d\n",v1,v2,f1,f2);
bel[f2]=f1;
}
}
int tot=0;
for(int i=1;i<=n;++i){
// printf("%d %d\n",i,find(i));
if(find(i)==i) id[i]=++tot;
}
bool chk=1;
for(int u=1;u<=n;++u){
for(int v:E1[u]){
if(find(u)==find(v)) chk=0;
else{
E3[id[find(u)]].push_back(id[find(v)]);
++deg[id[find(v)]];
}
}
}
queue<int> q;
if(deg[1]) chk=0;
f[1]=1;
q.push(1);
cnt=0;
while(!q.empty()){
int u=q.front();
q.pop();
++cnt;
for(int v:E3[u]){
f[v]=f[u]+1;
--deg[v];
if(!deg[v]) q.push(v);
}
}
if(cnt<tot) chk=0;
g[1]=1;
for(int v=2;v<=n;++v){
int u=E2[v][0];
g[v]=f[id[find(v)]]-f[id[find(u)]];
}
if(!chk) printf("No\n");
else{
printf("Yes\n");
for(int i=1;i<=n;++i) printf("%d ",g[i]);
printf("\n");
}
}
return 0;
}