- 原题链接:Here!
- 分析:因为最近一直在做拓扑排序的问题,所以没多想就采用拓扑排序来解决这个问题,后来一想,跟并查集好像......
1.判断图中是否存在环只需看能够处理多少节点,如果 处理节点数!=n,那肯定存在环。如果图中有环,那么在图中出现环的地方每个点的入度in[]肯定是无法=0的,所以环处的节点都不能进入队列,所以处理节点数目自然!=n。
2.其次这个问题还需要计算需要至少需要多少钱,其实很简单,对于二元关系(a,b),a的工资比b多1元即可。按照这个想法那需要记下每个节点的"层数",一开始入度为0的点自然工资最低,即888,由这些点能够拓展得到的其他点只需要+1即可。
3.一开始以为sum得挺大,用long long,后来验证一下发现sum最大5900w,int 足以。最坏是形成了一个链,888*n+(0+n-1)*n/2,n<=10000,5900w
- CODE
#include<cstdio> #include<cstring> #include<queue> #include<vector> using namespace std; //#define test const int maxn = 10000+10; int n,m; int topo[maxn]; int in[maxn]; vector<int> G[maxn]; int sum; int arr[maxn]; struct cmp{ bool operator()(int &a,int &b){ return a < b; } }; void topo_sort(){ queue<int> Q; memset(arr,-1,sizeof(arr)); for(int i=1;i<=n;i++) if(!in[i]){ Q.push(i); arr[i]=0; } while(!Q.empty()){ int u=Q.front(); Q.pop(); topo[ ++topo[0] ]=u; for(int v=0 ; v<G[u].size() ; v++){ in[ G[u][v] ]--; if(in[ G[u][v] ]==0){ Q.push( G[u][v] ); arr[ G[u][v] ]=arr[u]+1; } } } } int main(){ int a,b; #ifdef test freopen("Hdu 2647.txt","r",stdin); #endif while(scanf("%d%d",&n,&m)!=EOF){ for(int i=1 ; i<=n ; i++) G[i].clear(); memset(in,0,sizeof(in)); memset(topo,0,sizeof(topo)); for(int i=1 ; i<=m ; i++){ scanf("%d%d",&a,&b); G[b].push_back(a); // b指向a in[a]++; } topo_sort(); sum=0; if(topo[0]!=n) printf("-1\n"); else{ for(int i=1 ; i<=n ; i++) sum+=arr[i]; printf("%d\n",sum+(n*888)); } } return 0; } /* Test Data: 5 4 2 1 3 2 1 3 1 4 5 4 3 2 2 1 1 4 4 5 3 1 1 2 3 3 1 2 2 3 3 1 4 4 1 2 2 3 1 4 3 4 */