题意简述:有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 ",x,y) #define pf(x) printf("%d ",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; }