Codeforces Round #545 (Div. 2) EF

E. Museums Tour

题意:有n个城市m条有向边,一周有d天,每个城市的博物馆在d的周期内定时开放和关闭,现在你在起点 1,每隔一天你必须走到相邻的某个城市去,你有无限时间,每个点每条边你也可以走无数次,求最多能欣赏多少个不同的博物馆。

借鉴这位大佬:hwim

思路:我们把每个点拆成d个点,第 i 个点代表第 i 天走到了这个城市,那么对于每条边 u->v,我们枚举天数 i,连接ui->vi+1,代表如果第 i 天走到了 u 点,可以在第 i+1 到达 v点,也就是说,如果我能达到 xi 点,那么时间肯定是第 i 天(mod d),然后根据拆点连接的边建图跑tarjan缩点,对于一个环内点 u,如果在 i 天 u 的博物馆开放,那么就把 ui 所属的的联通快加上一个贡献,且d个 u 只能对同一个联通快产生最多一个贡献,算完贡献,我们从起点所属联通快跑dp,即可求出答案。

#include
using namespace std;
const int maxn=5e6+10;
int Laxt[maxn],Next[maxn],To[maxn],cnt;
int Laxt2[maxn],Next2[maxn],To2[maxn],cnt2; 
int d,n,m,dfn[maxn],low[maxn],sk[maxn],vis[maxn];
int sz[maxn],dp[maxn],bel[maxn],Time,scc,top;
char s[100001][51];
void add(int u,int v)
{
	Next[++cnt]=Laxt[u];Laxt[u]=cnt;To[cnt]=v;
}
void add2(int u,int v)
{
	Next2[++cnt2]=Laxt2[u];Laxt2[u]=cnt2;To2[cnt2]=v;
}
int id(int a,int b)
{
	return (a-1)*d+b+1;
}
void tarjan(int u)
{
	dfn[u]=low[u]=++Time;
	sk[++top]=u;vis[u]=1;
	for(int i=Laxt[u];i;i=Next[i])
	{
		int v=To[i];
		if(!dfn[v])
		{
			tarjan(v);
			low[u]=min(low[u],low[v]);
		}
		else if(vis[v])
		low[u]=min(low[u],dfn[v]);
	}
	if(low[u]==dfn[u])
	{
		++scc;
		do{
			vis[sk[top]]=0;
			bel[sk[top--]]=scc;
		}while(sk[top+1]!=u);
	}
}
int dfs(int u)
{
	if(dp[u])return dp[u];
	int ans=0;
	for(int i=Laxt2[u];i;i=Next2[i])
	ans=max(ans,dfs(To2[i]));
	dp[u]=sz[u]+ans;
	return dp[u];
}
int main()
{
	int u,v;
	scanf("%d%d%d",&n,&m,&d);
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d",&u,&v);
		for(int j=0;j

F. Cooperative Game

题意:有10个人在链的起点,链的终点连接一个有向环,每次可以往前移动若干人一个距离,然后系统会告诉你这些人所在不同地点的个数,要你把10个人全部移到链和环的交点上去,链和环长度未知。

思路:先把 1 往前移动 s 次,2 往前移动 2s次 直到他们两相遇,假设环长度m,相遇地点距交点x,环长度为n,那么s=m+x+i*n,2s=m+x+j*n,相减得 s=(j-i)*n,那么m=(j-2*i)n-x,这个时候我们知道起点到交点的距离等于若干环的周长-x,那么此时我同时移动所有人,当他们第一次相遇时,肯定是在交点,搞定。

#include
using namespace std;
int res;
int getv()
{
    int x;
    cin>>res;
    for(int i=1;i<=res;i++)
        scanf("%d",&x);
}
int main()
{
    do
    {
        puts("next 0");getv();
        puts("next 0 1");getv();
    }while(res==3);
    do
    {
        puts("next 0 1 2 3 4 5 6 7 8 9");
        getv();
    }while(res==2);
    puts("done");
}

 

你可能感兴趣的:(图论----联通分量)