题目链接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;
}