[2016-2017 ACM-ICPC, South Pacific Regional Contest (SPPC 16)]E Election Frenzy
题目大意:给出一个无向图,要求给图黑白染色,要求每个点和它相邻的点中至少有一个白点和一个黑点,输出任意一种方案。由于边数可能非常大,所以某些点给出的信息是所有不与它相连的点。
题解:思路还是比较简单的,直接遍历做生成树,相连两点不同色,这样保证满足条件,时间复杂度\(O(n+m)\),至于遍历时怎么处理边非常多的问题,可以随便写个数据结构(set之类的)搞搞,这里我用的是并查集。
#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+10,maxm=5e5+10;
char readchar() {char ch;while ((ch=getchar())!='C' && ch!='N');return ch;}
int head[maxn],nxt[maxm],E[maxm],P[maxn],Ecnt;
int Col[maxn];
int vis[maxn];
int fa[maxn];
int n;
void Add_Edge(int x,int y)
{
nxt[++Ecnt]=head[x];head[x]=Ecnt;E[Ecnt]=y;
}
int Find(int x) {return fa[x]==x?x:fa[x]=Find(fa[x]);}
void DFS(int x,int col)
{
vis[x]=1;
fa[x]=Find(x-1);
Col[x]=col;
if (P[x]==0)
{
for (int i=head[x];i;i=nxt[i])
if (!vis[E[i]]) DFS(E[i],col^1);
}
else
{
int t=n+1;
for (int i=head[x];i;i=nxt[i])
{
t=Find(t-1);
while (t>E[i]) DFS(t,col^1),t=Find(t-1);
t=E[i];
}
t=Find(t-1);
while (t>0) DFS(t,col^1),t=Find(t-1);
}
}
int temp[maxn];
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
int k;
char ch=readchar();
if (ch=='N') P[i]=1;
scanf("%d",&k);
if ((k==0 && P[i]==0) || (k==n-1 && P[i]==1))
{
printf("Impossible\n");
return 0;
}
for (int j=0;j<k;j++) scanf("%d",&temp[j]);
sort(temp,temp+k);
for (int j=0;j<k;j++) Add_Edge(i,temp[j]);
}
for (int i=0;i<=n;i++) fa[i]=i;
for (int i=1;i<=n;i++) if (!vis[i]) DFS(i,0);
for (int i=1;i<=n;i++) printf("%c",Col[i]==0?'V':'S');
return 0;
}
评论 (0)