拓扑排序可以把一张图排序成 成一条(?
然后就可以解一些有层次感(?)的题
这道是真题来着。
如果这趟车次停靠了火车站 x,则始发站、终点站之间所有级别大于等于火车站 x 的都必须停靠。
那么就是说,不停的站肯定是要比停的站低级咯。
把低级连向高级。
注意:这里的低级是指起点与终点之间的低级,不是1-n
我被自己之前写的垃圾题解坑了半个小时
- 找入度为0的(事先要存好
- 让入度为0的点滚,并把与其相连的点入度-1
- 重复1,直到不剩点
里面还有一些小细节。相连的点如果入度-1后变成了0,那么应该给它赋一个负的、特定的值,让它避免在这一次while中被删掉,在即将结束这层while时再恢复0
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int in[1001],car[1001];
bool to[1001][1001],vis[1001];
int main()
{
ios::sync_with_stdio(0);
int n,m;
cin>>n>>m;
while(m--)
{
int t;
cin>>t;
memset(car,0,sizeof(car));
memset(vis,0,sizeof(vis));
for(int i=0;i<t;i++)
cin>>car[i],vis[car[i]]=1;
for(int i=car[0]+1;i<car[t-1];i++)//在起点和终点间枚举!
if(!vis[i])//标记这车站有没有停过(就是高不高级的意思)
for(int j=0;j<t;j++)
if(!to[i][car[j]])
{
to[i][car[j]]=1;
in[car[j]]++;
}
}
int pp=0,ans=0;
while(n-pp)
{
ans++;
for(int i=1;i<=n;i++)
if(!in[i])
{
in[i]=-1;
pp++;
for(int j=1;j<=n;j++)
if(to[i][j])
{
to[i][j]=0;
if(in[j]>0)
in[j]--;
if(!in[j])
in[j]=-2;
}
}
for(int i=1;i<=n;i++)
if(in[i]==-2)
in[i]=0;
}
cout<<ans;
return 0;
}
然后昨晚我在犇犇问了下这个
过了一会,被dalao回复了。
这个那么经典你确定没见过?
我,又在洛谷丢人了
1038图太糊,不写。
我去写了下usaco的杂物。
这题的数据实在太垃圾了,好多人根本不是拓扑。
用spfa和递推也可以过。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
inline void in(int &p,char c=getchar())
{
while(c<'0' or c>'9')
c=getchar();
p=0;
while(c>='0' and c<='9')
p=p*10+c-'0',c=getchar();
}
struct task
{
int num;
int cost;
int ru;
vector <int> nxt;
}a[10001];
long long ans,f[10001];
int main()
{
int n;
in(n);
for(int i=1;i<=n;i++)
{
in(a[i].num);
in(a[i].cost);
int x;
in(x);
while(x)
{
a[x].nxt.push_back(i);
a[i].ru++;
in(x);
}
}
for(int i=1;i<=n;i++)
if(!a[i].ru)
f[i]=a[i].cost;
int pp=0;
while(n-pp)
{
for(int i=1;i<=n;i++)
if(!a[i].ru)
{
pp++;
a[i].ru=-1;
ans=max(ans,f[i]);
for(unsigned j=0;j<a[i].nxt.size();j++)
{
int v=a[i].nxt[j];
f[v]=max(f[v],f[i]+a[v].cost);
if(a[v].ru>1)
a[v].ru--;
else
a[v].ru=-2;
}
}
for(int i=1;i<=n;i++)
if(a[i].ru==-2)
a[i].ru=0;
}
cout<<ans;
return 0;
}