cf949C
题意简述:有n个点,每一个点都有一个权值,然后有m个条件,每一个条件是a[x]!=a[y],让选择最少的点且至少选择1个,然后让这个点的权值+1,使得条件仍满足
所有数对k取模
题解:如果a[x]+1=a[y]那么x向y连边,a[y]+1=a[x]那么y向x连边,此时答案等于缩点之后出度为0的分量中点最少的一个
#include<bits/stdc++.h>
#define forn(i, n) for (int i = 0 ; i < int(n) ; i++)
#define fore(i, s, t) for (int i = s ; i < (int)t ; i++)
#define fi first
#define se second
#define all(x) x.begin(),x.end()
#define pf2(x,y) printf("%d %d\n",x,y)
#define pf(x) printf("%d\n",x)
#define each(x) for(auto it:x) cout<<it<<endl;
#define pi pair<int,int>
using namespace std;
typedef long long ll;
const int maxn=1e6+5;
const int maxm=2e5+5;
const int inf=1e9;
int head[maxn],ver[maxm],nex[maxm],tot;
void inline AddEdge(int x,int y){
ver[++tot]=y,nex[tot]=head[x],head[x]=tot;
}
int dfn[maxn],low[maxn],num,sccnum,scc[maxn],s[maxn],d[maxn],cnt[maxn],top;
void Tarjan(int x){
low[x]=dfn[x]=++num;
s[++top]=x;
for(int i=head[x];i;i=nex[i]){
int y=ver[i];
if(!dfn[y]) {
Tarjan(y);
low[x]=min(low[x],low[y]);
}
else if(!scc[y]) low[x]=min(low[x],dfn[y]);
}
if(low[x]==dfn[x]){
sccnum++;
while(s[top]!=x){
scc[s[top]]=sccnum;
top--;
cnt[sccnum]++;
}
cnt[sccnum]++;
scc[s[top]]=sccnum;
top--;
}
}
int n,m,k,a[maxn];
int main(){
cin>>n>>m>>k;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=0;i<m;i++){
int x,y;
scanf("%d%d",&x,&y);
if((a[x]+1)%k==a[y]) AddEdge(x,y);
if((a[y]+1)%k==a[x]) AddEdge(y,x);
}
for(int i=1;i<=n;i++)
if(!dfn[i]) Tarjan(i);
for(int x=1;x<=n;x++)
for(int i=head[x];i;i=nex[i]){
int y=ver[i];
if(scc[x]!=scc[y]) {
d[scc[x]]++;
}
}
int idx=0;
cnt[idx]=1e9;
for(int i=1;i<=n;i++){
if(d[scc[i]]==0 && cnt[scc[i]]<cnt[scc[idx]])
idx=i;
}
cout<<cnt[scc[idx]]<<endl;
for(int i=1;i<=n;i++)
if(scc[idx]==scc[i]) cout<<i<<' ';
cout<<endl;
return 0;
}
浙公网安备 33010602011771号