Codeforces Round #469 (Div. 1) 949C C. Data Center Maintenance (Div. 2 950E)

  OvO http://codeforces.com/contest/949/problem/C

  codeforces 949C 950E

  建图,记原图为 G1,缩点,记缩完点后的新图为G2

  缩完点后的图 G2 必定无环,求这个无环图 G2 中每个点的入度,

  找出入度0 的那些点,记这些点的集合为 S,然后把 S 中这些点映射到 G1 中,则这些点各自对应一个点集。的各点中,对应的最小集合即为所求集合

 

#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cstdio>
#include <queue>
#include <vector>
#include <stack>

using namespace std;

const int N=100044;  
const int INF=1e9+44;

struct data  
{  
    int to,next;  
} tu[N*2];  

struct sav
{
	int a,b;
} edgsav[N*2];

int head[N];  
int ip;  
int dfn[N], low[N];///dfn[]表示深搜的步数,low[u]表示u或u的子树能够追溯到的最早的栈中节点的次序号  
int sccno[N];///缩点数组,表示某个点对应的缩点值  
int step;  
int scc_cnt;///强连通分量个数  
int n,m,h,u[N];
int ind[N],outd[N];
int edgnum;

void init()  
{  
    ip=0;  
    edgnum=0;
    memset(head,-1,sizeof(head));  
    memset(ind,0,sizeof(ind));
    memset(outd,0,sizeof(outd));
}  

void add(int u,int v)  
{  
	edgnum++,edgsav[edgnum].a=u,edgsav[edgnum].b=v;
    tu[ip].to=v,tu[ip].next=head[u],head[u]=ip++;  
}  

vector<int> scc[N];///得出来的缩点,scc[i]里面存i这个缩点具体缩了哪些点  
stack<int> S;  

void dfs(int u)  
{  
    dfn[u] = low[u] = ++step;  
    S.push(u);  
    for (int i = head[u]; i !=-1; i=tu[i].next)  
    {  
        int v = tu[i].to;  
        if (!dfn[v])  
        {  
            dfs(v);  
            low[u] = min(low[u], low[v]);  
        }  
        else if (!sccno[v])  
            low[u] = min(low[u], dfn[v]);  
    }  
    if (low[u] == dfn[u])  
    {  
        scc_cnt += 1;  
        scc[scc_cnt].clear();  
        while(1)  
        {  
            int x = S.top();  
            S.pop();  
            if (sccno[x] != scc_cnt) scc[scc_cnt].push_back(x);  
            sccno[x] = scc_cnt;  
            if (x == u) break;  
        }  
    }  
}  

void tarjan(int n)  
{  
    memset(sccno, 0, sizeof(sccno));  
    memset(dfn, 0, sizeof(dfn));  
    step = scc_cnt = 0;  
    for (int i = 1; i <=n; i++)  
        if (!dfn[i]) dfs(i);  
}  

inline int trans(int x)
{
	return (x+1)%h;
} 

int main()
{
	int a,b;
	init();
	scanf("%d%d%d",&n,&m,&h);
	for(int i=1;i<=n;i++)
		scanf("%d",&u[i]);
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d",&a,&b);
		if(trans(u[a])==u[b]) add(a,b);
		if(trans(u[b])==u[a]) add(b,a);
	}
	tarjan(n);
	for(int i=1;i<=edgnum;i++)
		if(sccno[edgsav[i].a]!=sccno[edgsav[i].b])
		{
			outd[sccno[edgsav[i].a]]++;
			ind[sccno[edgsav[i].b]]++;
		}
	int the,tmp=INF;
	for(int i=1;i<=scc_cnt;i++)
		if(outd[i]==0 && scc[i].size()<tmp)
			the=i,tmp=scc[i].size();
	printf("%d\n",tmp);
	for(int i=0;i<scc[the].size();i++)
	{
		printf("%d",scc[the][i]);
		if(i==scc[the].size()-1) puts("");
		else printf(" ");
	}
	return 0;
}

  

posted @ 2018-03-09 20:39  太阳星人FxxL  阅读(980)  评论(0编辑  收藏  举报