题目链接https://vjudge.net/contest/151613#problem/C
题意:给你n个点,有m个要求,要求中有两个数,表示第一个点的值要大于第二点的值。拓扑排序。
代码:
#include <iostream> #include <bits/stdc++.h> using namespace std; pair<int ,int>p; vector<int>g[10005]; int degree[10005]; long long topo(int n) { long long ans=0; queue<pair<int,int> > q; int tot=0; int cnt=0; for(int i=1;i<=n;i++) { if(degree[i]==0) { p.first=i,p.second=888; q.push(p); } } while(q.size()) { pair<int,int>qq=q.front(); q.pop(); tot++; ans+=qq.second; for(int j=0;j<g[qq.first].size();j++) { degree[g[qq.first][j]]--; if(degree[g[qq.first][j]]==0) { p.second=qq.second+1; p.first=g[qq.first][j]; q.push(p); } } } if(tot==n) return ans; else return 0; } int main() { int n,m; while(scanf("%d%d",&n,&m)!=EOF) { memset(degree,0,sizeof(degree)); memset(g,0,sizeof g); for(int i=0;i<m;i++) { int a,b; scanf("%d%d",&a,&b); degree[a]++; g[b].push_back(a); } long long an=topo(n); if(an==0) puts("-1"); else printf("%lld\n",an); } return 0; }这一题跟前面的A、B题略有不同。需要知道每个节点的出度是多少,因为出度的值会影响这个点的值,所以需要用pair去保存这个点和这个点的值,最后加起来就可以了
从出度为0的点开始操作,然后将相连点中出度为0的压入队列中,点值+1即可。
topo一般模版:
#include <iostream> #include <bits/stdc++.h> using namespace std; vector<TYPE>g[MAX_N]; //TYPE可以根据需要进行修改 int degree[MAX_N]; int topo(int n) { queue<TYPE>q; memset(degree,0,sizeof(degree)); //注意初始化 for(int i=0;i<n;i++) //注意数据的给法是从0开始还是1开始 { for(int j=0;j<g[i].size();j++) { degree[g[i][j]]++; } } for(int i=0;i<n;i++) //注意数据的给法是从0开始还是1开始 { if(degree[i]==0) { q.push(i); } } int tot=0; while(q.size()) { int qq=q.front(); //根据类型修改qq的类型 q.pop(); tot++; for(int i=0;i<g[qq].size();i++) { degree[g[qq][i]]--; if(degree[g[qq][i]]==0) q.push(g[qq][i]); } } if(tot==n) //判断自环 return 1; else return 0; } int main() { int n,m; while(scanf("%d%d",&n,&m)!=EOF) { memset(g,0,sizeof(g)); int a,b; for(int i=0;i<m;i++) { scanf("%d%d",&a,&b); g[a].push_back(b); //根据TYPE的类型和出度入度的不同,这里会有所不同 } if(topo(n)) printf("YES\n"); else printf("NO\n"); } return 0; }