问题1.判断有没有环
http://hihocoder.com/problemset/problem/1174
用vector模拟邻接表,开一个记录入度的一维数组,一个存储入度为0的队列
ac代码如下
#include<iostream> #include<algorithm> #include<vector> #include<queue> #include<string.h> using namespace std; typedef long long int ll; int n,k,a,b,t,m; const int maxn=1e5+5; vector<int>v[maxn]; queue<int>q; int indge[maxn]; bool judge() { int num=0; while(!q.empty())q.pop(); for(int i=1;i<=n;i++){ if(!indge[i])q.push(i); } while(!q.empty()){ int tot=q.front(); q.pop(); num++; for(int i=0;i<v[tot].size();i++){ if(--indge[v[tot][i]]==0)q.push(v[tot][i]); } } if(num==n)return true; else return false; } int main() { cin>>t; for(int i=1;i<=t;i++){ cin>>n>>m; for(int i=0;i<maxn;i++)v[i].clear(); memset(indge,0,sizeof(indge)); for(int j=0;j<m;j++){ cin>>a>>b; v[a].push_back(b); indge[b]++; } if(judge())puts("Correct"); else puts("Wrong"); } return 0; } /* 2 2 2 1 2 2 1 3 2 1 2 1 3 */
问题2:给定一个dag图,给定一些点病毒为1,他们为传染给后继结点,依次类推,求最终的病毒数量
http://hihocoder.com/problemset/problem/1175
#include<iostream> #include<algorithm> #include<vector> #include<queue> #include<string.h> using namespace std; typedef long long int ll; int n,k,m,b,t1,t2; const int maxn=1e5+5; const int mod=142857; vector<int>v[maxn]; vector<ll>a(maxn); queue<int>q; int indge[maxn]; void res() { while(!q.empty())q.pop(); for(int i=1;i<=n;i++){ if(!indge[i])q.push(i); } while(!q.empty()){ int tot=q.front(); q.pop(); for(int i=0;i<v[tot].size();i++){ a[v[tot][i]]=(a[v[tot][i]]+a[tot])%mod; if(--indge[v[tot][i]]==0){ q.push(v[tot][i]); } } } } int main() { for(int i=0;i<maxn;i++)v[i].clear();a.clear(); cin>>n>>m>>k; for(int i=0;i<k;i++){ cin>>b; a[b]=1; } memset(indge,0,sizeof(indge)); for(int j=0;j<m;j++){ cin>>t1>>t2; v[t1].push_back(t2); indge[t2]++; } res(); long long int ans=0; for(int i=1;i<=n;i++){ ans=(ans+a[i])%mod;//; } cout<<ans<<endl; return 0; } /* 2 2 2 1 2 2 1 3 2 1 2 1 3 */
洛谷 P4017 最大食物链计数
https://www.luogu.com.cn/problem/P4017
题目是找生产者到最高级消费者的路线有几条。
其实是找入度为0的点到出度为0的路径方式有几种。
预处理入度和出度,拓扑排序,把出度为0的点的路线累加。
#include<iostream> #include<algorithm> #include<cstdio> #include<vector> #include<queue> #include<map> #include<string.h> using namespace std; typedef long long int ll; int n,k,m,b,t,t1,t2,t3,maxx=0; const int maxn=1e5+5; const int mod= 80112002; vector<int >v[maxn]; vector<int>a(maxn); queue<int>q; int indge[maxn]; int outdge[maxn]; void topsort() { int num=0; while(!q.empty())q.pop(); for(int i=1;i<=n;i++){ if(!indge[i]){ a[i]=1; q.push(i); } } while(!q.empty()){ int tot=q.front(); q.pop(); num++; for(int i=0;i<v[tot].size();i++){ if(--indge[v[tot][i]]==0){ q.push(v[tot][i]); } a[v[tot][i]]=(a[v[tot][i]]+a[tot])%mod; } } } int main() { scanf("%d%d",&n,&m); for(int i=0;i<maxn;i++)v[i].clear();a.clear(); memset(indge,0,sizeof(indge)); memset(outdge,0,sizeof(outdge)); for(int j=0;j<m;j++){ //cin>>t1>>t2>>t3; scanf("%d%d",&t1,&t2); v[t1].push_back(t2); indge[t2]++; outdge[t1]++; } topsort(); int ans=0; for(int i=1;i<=n;i++){ if(outdge[i]==0)ans=(ans+a[i])%mod; } cout<<ans<<endl; return 0; }
洛谷 P1807 最长路
https://www.luogu.com.cn/problem/P1807
一道裸的dag拓扑排序加上了权值,vector模拟邻接表存出边和权值,dp数组更新最长路。
/* 展开 题目描述 设 G 为有 n 个顶点的带权有向无环图,G 中各顶点的编号为 1 到 n,请设计算法,计算图 GG 中 <1,n><1,n> 间的最长路径。 输入格式 输入的第一行有两个整数,分别代表图的点数 n 和边数 m。 第 2 到第 (m+1) 行,每行 3 个整数 u, v,w,代表存在一条从 u 到 v 边权为w的边。 输出格式 输出一行一个整数,代表 1 到 n 的最长路。 若 1 与 n 不联通,请输出 -1。 */ #include<bits/stdc++.h> using namespace std; const int maxn=1e4+5; int indge[maxn],dp[maxn],bj[maxn]; int n,m; vector<pair<int,int> >v[maxn]; void topsort() { queue<int>q; while(!q.empty())q.pop(); for(int i=1;i<=n;i++){ if(!indge[i])q.push(i); } while(!q.empty()){ int k=q.front();q.pop(); for(int i=0;i<v[k].size();i++){ if(--indge[v[k][i].first]==0)q.push(v[k][i].first); if(bj[k]){ dp[v[k][i].first]=max(dp[v[k][i].first],dp[k]+v[k][i].second);///自身的长度与父亲节点的最长路加上父亲到儿子这条边的长度比较 bj[v[k][i].first]=1; } } } } int main() { cin>>n>>m; int a,b,c; memset(indge,0,sizeof(indge)); memset(dp,0,sizeof(dp)); memset(bj,0,sizeof(bj)); for(int i=0;i<m;i++){ cin>>a>>b>>c; v[a].push_back(make_pair(b,c)); indge[b]++; } dp[n]=-1,bj[1]=1;///初始化dp[n]=-1,输出方便,bj[1]=1,标记1能到达点 topsort(); cout<<dp[n]<<endl; return 0; }