拓扑排序模板:
vector<int> g[N];
queue<int> q;
int deg[N];//出度数
for (int i = 1; i <= n; i++)
if (deg[i] == 0)
q.push(i);//初始化,将叶子节点加入队列
int cnt = 0;
while (!q.empty())
{
int t = q.front();
q.pop();
ans[++cnt] = t;
for (auto i : g[t])
{
deg[i]--;//该点的孩子被pop,出度减1
if (deg[i] == 0)//该点称为叶子节点,加入队列
q.push(i);
}
}
Codeforces Round #748 (Div. 3)
E. Gardener and Tree
题目大意:修剪一棵树,每次操作将树的叶子节点删掉,询问k次操作后,树还剩下几个节点。
思路:
对初始树进行拓扑排序,求出每个节点的前继的个数,度数为1的是叶节点,前继的个数(层数)显然等于该点在第几轮删除中被删掉,用桶记录一下每层的节点个数,将大于k层的求和输出即可
代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 401000;
vector<int>g[N];
queue<int>q;
int deg[N],ans[N];
int dep[N],dp1[N];
int main()
{
int T;
cin>>T;
while(T--)
{
memset(deg,0,sizeof(deg));
memset(dp1,0,sizeof(dp1));
memset(dep,0,sizeof(dep));
int n,k;
cin>>n>>k;
for(int i=1;i<=n;i++)
g[i].clear();
for(int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
g[x].push_back(y);
g[y].push_back(x);
deg[x]++;
deg[y]++;
}
for(int i=1;i<=n;i++)
if(deg[i]==1)
q.push(i),dep[i]=1;
int cnt=0;
while(!q.empty())
{
int t=q.front();
q.pop();
ans[++cnt]=t;
for(auto i:g[t])
{
deg[i]--;
if(deg[i]==1)
{
q.push(i);
dep[i]=dep[t]+1;//如果该节点被push,说明t是该节点的孩子,层数+1
}
}
}
int sum=0;
int maxd=0;
for(int i=1;i<=n;i++)
maxd=max(maxd,dep[i]),dp1[dep[i]]++;
for(int i=k+1;i<=maxd;i++)
sum+=dp1[i];
cout<<sum<<endl;
}
}
杂务(拓扑排序+dp)
题目大意:
给你很多工作,有一些工作需要前置工作,现在给出所有工作的前置工作和每个工作需要的时间,工人可以多线程工作,即可以同时做所有能做的工作,求最少工作时间:
思路
对所有工作拓扑排序,用dp维护当前最少工作时间,转移方程为: dp[i] = max(dp[i], dp[t] + tim[i]);
#include <bits/stdc++.h>
using namespace std;
const int N = 10100;
vector<int> g[N];
queue<int> q;
int deg[N];
int ans[N];
int tim[N];
int dp[N];
int main()
{
int n;
cin >> n;
for (int i = 1; i <= n; i++)
{
int x;
cin >> x;
int ti;
cin >> ti;
tim[x] = ti;
int j;
while (cin >> j && j)
{
g[j].push_back(i);
deg[i]++;
}
}
for (int i = 1; i <= n; i++)
if (deg[i] == 0)
q.push(i), dp[i] = tim[i];
int cnt = 0;
while (!q.empty())
{
int t = q.front();
q.pop();
ans[++cnt] = t;
for (auto i : g[t])
{
deg[i]--;
if (deg[i] == 0)
q.push(i);
dp[i] = max(dp[i], dp[t] + tim[i]);
}
}
int sum = 0;
for (int i = 1; i <= n; i++)
sum = max(sum, dp[i]);
cout << sum << endl;
}