题意:有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<bits/stdc++.h>
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<d;j++)
add(id(u,j),id(v,(j+1)%d));
}
for(int i=1;i<=n;i++)
scanf("%s",s[i]);
for(int i=1;i<=n*d;i++)
if(!dfn[i])tarjan(i);
for(int i=1;i<=n;i++)
for(int j=0;j<d;j++)
{
int x=id(i,j);
if(s[i][j]=='1'&&vis[bel[x]]!=i)
vis[bel[x]]=i,sz[bel[x]]++;
for(int k=Laxt[x];k;k=Next[k])
{
int v=To[k];
if(bel[x]!=bel[v])
add2(bel[x],bel[v]);
}
}
printf("%d\n",dfs(bel[1]));
}
题意:有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<bits/stdc++.h>
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");
}