意甲冠军:特定n积分。m向边条。
该点被划分成多个集合随机的每个集合,使得2问题的关键是无法访问(集合只能容纳一个点)
问至少需要被分成几个集合。
假设没有戒指,接着这个话题正在寻求产业链最长的一个有向图。拓扑序运行bfs您可以。
但是有一个环,所以把环缩点成新点x。而点x的点权就是x点在原图中相应的顶点个数。
缩点后就是有向无环图,继续跑一个拓扑序。
#include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <set> #include <map> #include <string> #include <math.h> #include <stdlib.h> #include <time.h> using namespace std; #define N 100010 //N为最大点数 #define M 301000 //M为最大边数 int n, m;//n m 为点数和边数 struct Edge{ int from, to, nex; bool sign;//是否为桥 }edge[M<<1]; int head[N], edgenum; void add(int u, int v){//边的起点和终点 Edge E={u, v, head[u], false}; edge[edgenum] = E; head[u] = edgenum++; } int DFN[N], Low[N], Stack[N], top, Time; //Low[u]是点集{u点及以u点为根的子树} 中(全部反向弧)能指向的(离根近期的祖先v) 的DFN[v]值(即v点时间戳) int taj;//连通分支标号。从1開始 int Belong[N];//Belong[i] 表示i点属于的连通分支 bool Instack[N]; vector<int> bcc[N]; //标号从1開始 void tarjan(int u ,int fa){ DFN[u] = Low[u] = ++ Time ; Stack[top ++ ] = u ; Instack[u] = 1 ; for (int i = head[u] ; ~i ; i = edge[i].nex ){ int v = edge[i].to ; if(DFN[v] == -1) { tarjan(v , u) ; Low[u] = min(Low[u] ,Low[v]) ; if(DFN[u] < Low[v]) { edge[i].sign = 1;//为割桥 } } else if(Instack[v]) Low[u] = min(Low[u] ,DFN[v]) ; } if(Low[u] == DFN[u]){ int now; taj ++ ; bcc[taj].clear(); do{ now = Stack[-- top] ; Instack[now] = 0 ; Belong [now] = taj ; bcc[taj].push_back(now); }while(now != u) ; } } void tarjan_init(int all){ memset(DFN, -1, sizeof(DFN)); memset(Instack, 0, sizeof(Instack)); top = Time = taj = 0; for(int i=1;i<=all;i++)if(DFN[i]==-1 )tarjan(i, i); //注意開始点标!。!} vector<int>G[N]; int du[N]; void suodian(){ for(int i = 1; i <= taj; i++)G[i].clear(), du[i] = 0; for(int i = 0; i < edgenum; i++){ int u = Belong[edge[i].from], v = Belong[edge[i].to]; if(u!=v)G[u].push_back(v), du[v]++; } } void init(){memset(head, -1, sizeof(head)); edgenum=0;} int dis[N]; int bfs(){ queue<int>q; for(int i = 1; i <= taj; i++) if(du[i]==0){q.push(i); dis[i] = bcc[i].size();} else dis[i] = 0; while(!q.empty()){ int u = q.front(); q.pop(); for(int i = 0; i < G[u].size(); i++){ int v = G[u][i]; dis[v] = max(dis[u]+(int)bcc[v].size(), dis[v]); du[v]--; if(du[v]==0) q.push(v); } } int ans = 1; for(int i = 1; i <= taj; i++)ans = max(ans, dis[i]); return ans; } int main() { int i,j,u,v; while(~scanf("%d %d",&n,&m)){ init(); while(m--){ scanf("%d %d",&u,&v); if(u!=v) add(u,v); } tarjan_init(n); suodian(); printf("%d ",bfs()); } return 0; } /* 5 5 1 2 2 3 3 4 4 1 5 1 4 4 1 2 2 3 3 4 4 1 5 3 1 2 2 3 3 4 */