CF949C Data Center Maintenance

题意

有n个信息中心,第i个信息中心要在第ti时刻维护,每个用户都将资料存档在了两个中心,你现在要选一个最小的集合,使得维修时间推迟一小时后,用户还能获得信息

思路 

对于每对冲突的点连边,然后求强连通分量,答案就是缩点后度数为零且最小的SCC

代码

//By AcerMo%%%尹兄 
#include<cmath>
#include<stack>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int M=200500; 
int n,m,h;
int low[M],dfn[M],fa[M],in[M];
int vis[M],ind=0,ti=0,t[M],siz[M];
stack<int>s;
vector<int>v[M];
inline int read()
{
	int x=0;char ch=getchar();
	while (ch>'9'||ch<'0') ch=getchar();
	while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
	return x;
}
inline void tarjan(int x)
{
	low[x]=dfn[x]=++ind;vis[x]=1;s.push(x);
	for (int i=0;i<v[x].size();i++)
	{
		int go=v[x][i];
		if (!dfn[go])
		{
			tarjan(go);
			low[x]=min(low[x],low[go]);
		}
		else if (vis[go])
			low[x]=min(low[x],dfn[go]);
	}
	if (low[x]==dfn[x])
	{
		ti++;int u=-1;
		while (u!=x)
		{
			u=s.top();s.pop();
			vis[u]=0;fa[u]=ti;
			siz[ti]++;
		}
	}
	return ;
}
int main()
{
	n=read();m=read();h=read();
	for (int i=1;i<=n;i++) t[i]=read();
	for (int i=1;i<=m;i++)
	{
		int x=read(),y=read();
		if (t[x]==(t[y]+1)%h) v[y].push_back(x);
		if (t[y]==(t[x]+1)%h) v[x].push_back(y);
	}
	for (int i=1;i<=n;i++)
		if (!dfn[i]) tarjan(i);
	for (int i=1;i<=n;i++)
		for (int k=0;k<v[i].size();k++)
			if (fa[i]!=fa[v[i][k]]) in[fa[i]]++;
	siz[0]=n+1;int ans=0;
	for (int i=1;i<=ti;i++)
		if (!in[i]&&siz[i]<siz[ans]) ans=i;
	cout<<siz[ans]<<endl;
	for (int i=1;i<=n;i++)
		if (fa[i]==ans) 
			cout<<i<<" ";
	return 0;
}

猜你喜欢

转载自blog.csdn.net/acerandaker/article/details/80977450