原代码 O(n2): 772ms
#include<bits/stdc++.h> #define int long long using namespace std; const int N=1e6+10,M=1e4+10; int n,m,res,f[N],p[N],a[N],s,k,level[N]; int e[N],ne[N],h[N],idx; bool vis[N],mp[M][M]; void add(int a,int b) { e[idx]=b,ne[idx]=h[a],h[a]=idx++; } void topsort() { queue<int>que; for(int i=1;i<=n;i++) if(!p[i]) que.push(i); while(!que.empty()){ int now=que.front(); que.pop(); for(int i=h[now];~i;i=ne[i]){ int j=e[i]; p[j]--; if(p[j]==0) level[j]=level[now]+1,que.push(j); } } } void spfa() { queue<int>que; que.push(0),level[0]=0,vis[0]=true; while(!que.empty()){ int now=que.front(); que.pop(); vis[now]=false; for(int i=h[now];~i;i=ne[i]){ int j=e[i]; if(level[j]<level[now]+1){ level[j]=level[now]+1; if(!vis[j]) vis[j]=true,que.push(j); } } } } int dfs(int u) { if(level[u]) return level[u]; for(int i=h[u];~i;i=ne[i]) level[u]=max(level[u],dfs(e[i])+1); return level[u]; } signed main() { std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); cin>>n>>m; memset(h,-1,sizeof h); //memset(level,-0x3f,sizeof level); for(int i=0;i<m;i++){ cin>>k; memset(vis,false,sizeof vis); for(int j=0;j<k;j++) cin>>a[j],vis[a[j]]=true; for(int j=a[0];j<=a[k-1];j++){ if(vis[j]) continue; for(int e=0;e<k;e++) if(!mp[a[e]][j]) mp[a[e]][j]=true,add(a[e],j),p[j]++;//spfa是add(j,a[e]) } } memset(vis,false,sizeof vis); //for(int i=1;i<=n;i++) add(0,i); //topsort(); //spfa(); //for(int i=1;i<=n;i++) res=max(res,level[i]); for(int i=1;i<=n;i++) if(!p[i]) res=max(res,dfs(i)); //cout<<res<<endl; cout<<res+1<<endl; return 0; }
考虑优化:
O(nm)
244ms / 13.34MB / 0.69KB
原本要连n2条边
但是,如果在中间添加一个虚点,就可以变成2n条边
#include<bits/stdc++.h> #define int long long using namespace std; const int N=1e6+10,M=1e4+10; int n,m,res,f[N],p[N],a[N],s,k,level[N]; int e[N],ne[N],h[N],idx; bool vis[N],mp[M][M]; void add(int a,int b) { e[idx]=b,ne[idx]=h[a],h[a]=idx++; } void topsort() { queue<int>que; for(int i=1;i<=n;i++) if(!p[i]) que.push(i); while(!que.empty()){ int now=que.front(); que.pop(); for(int i=h[now];~i;i=ne[i]){ int j=e[i]; p[j]--; if(p[j]==0) level[j]=level[now]+1,que.push(j); } } } void spfa() { queue<int>que; que.push(0),level[0]=0,vis[0]=true; while(!que.empty()){ int now=que.front(); que.pop(); vis[now]=false; for(int i=h[now];~i;i=ne[i]){ int j=e[i]; if(level[j]<level[now]+1){ level[j]=level[now]+1; if(!vis[j]) vis[j]=true,que.push(j); } } } } int dfs(int u) { if(level[u]) return level[u]; for(int i=h[u];~i;i=ne[i]) level[u]=max(level[u],dfs(e[i])+1); if(u>n) level[u]--;//这里注意,如果u层更新完了之后还是处于虚点,那就是没出去,要减1 return level[u]; } signed main() { std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); cin>>n>>m; memset(h,-1,sizeof h); //memset(level,-0x3f,sizeof level); for(int i=1;i<=m;i++){ cin>>k; memset(vis,false,sizeof vis); for(int j=1;j<=k;j++) cin>>a[j],vis[a[j]]=true,add(n+i,a[j]); for(int j=a[1];j<=a[k];j++){ if(vis[j]) continue; // for(int e=0;e<k;e++) // if(!mp[a[e]][j]) mp[a[e]][j]=true,add(a[e],j),p[j]++;//spfa是add(j,a[e]) add(j,n+i);//连入虚点 } } memset(vis,false,sizeof vis); //for(int i=1;i<=n;i++) add(0,i); //topsort(); //spfa(); //for(int i=1;i<=n;i++) res=max(res,level[i]); for(int i=1;i<=n;i++) if(!level[i]) res=max(res,dfs(i)); cout<<res<<endl; //cout<<res+1<<endl; return 0; }