本题主要思路:
sum=a1+……+an
cnt[i] 相当于 ai的值
1.如果sum<=1e9 并且 不存在环 ,即有解,输出sum
2.若sum>1e9不符合题目要求 或 存在环(则必定有某些点遍历不到cnt[i]=0) ,无解,输出-1/* 本题思路: sum=a1+……+an cnt[i]相当于ai的值 1.如果sum<=1e9 并且 不存在环 ,即有解,输出sum 2.若sum>1e9不符合题目要求 或 存在环(则必定有某些点遍历不到cnt[i]=0) ,无解,输出-1 */ #include<bits/stdc++.h> using namespace std; #define PII pair<int,int> const int N = 2e5+10; //邻接表存图 int h[N],e[N],ne[N],idx; int n,m; int d[N],cnt[N];//d[]代表出度,cnt[]代表最小取值 queue<int> p;//队列 vector<PII> son[N];//son[i]记录点i的一对儿子first和second //建边:a指向b void add(int a,int b) { e[idx]=b,ne[idx]=h[a],h[a]=idx++; } //拓扑排序 void topp() { //遍历n个点 for(int i=1;i<=n;i++) { //如果出度为0,则设置最小值 1 if(d[i]==0) { p.push(i); cnt[i]=1; } } while(p.size()) { auto t = p.front(); p.pop(); //遍历点t的每个父节点 for(int i=h[t];i!=-1;i=ne[i]) { int j=e[i]; d[j]--; //若有环的存在,有些点不会d[j]永远大于0,不会进来 //如果出度为0时,说明点j的每个儿子节点cnt[]值已经确定 if(d[j]==0) { //遍历点j的每个儿子对,取最大值. 因为ai>=ai1+ai2 for(auto i:son[j]) { cnt[j]=max(cnt[j],cnt[i.first]+cnt[i.second]); } //将j压入队列 p.push(j); } } } } int main() { memset(h,-1,sizeof(h)); cin>>n>>m; int x,y,z; while(m--) { cin>>x>>y>>z; //这里存的是儿子节点指向父节点,从下往上搜 add(y,x); add(z,x); //记录x的每一对儿子{y,z} son[x].push_back({y,z}); d[x]+=2;//出度+2 } //拓扑排序主函数 topp(); /* 1.有环或自环的存在,则必定存在某一点到达不了,且出度>0,所以cnt[i]=0 */ int sum; for(int i=1;i<=n;i++) { sum+=cnt[i]; // cout<<cnt[i]<<" "; //题目要求a1+……an<=1e9 if(cnt[i]==0 || sum>1e9) { puts("-1"); return 0; } } cout<<sum<<'\n'; return 0; }