您的位置:首页 > 其它

NOIP2013P4 车站分级 题解

2016-03-19 15:13 381 查看
(题目描述略)

本题为图论题。思路如下:

若一趟车次停靠了第i个节点和第j个节点,且第i个节点和第j个节点间无停靠点,则这趟车次所有停靠点级别必严格大于第i个节点和第j个节点中间所有的节点(不包括第i个节点和第j个节点)。换言之,所有已停靠的节点级别必严格大于起点站与终点站之间所有未停靠的节点(起点站与终点站算已停靠的节点)。

由此可以建有向图。当且仅当节点i级别严格大于节点j时,连一条有向边由i指向j(反之亦可),则将该问题转化为不含环的有向图中各边权值相等的最长路径问题。用拓扑排序即可解决。

代码如下:

#include"stdio.h"
#include"string.h"
bool array[2][1005],object[1005],repeat[1005][1005];
int a[1005],count[1005],map[1005][1005];
int main()
{
freopen("level.in","r",stdin);
freopen("level.out","w",stdout);
memset(array,false,sizeof(array));//滚动数组,记录入度为0的点
memset(count,0,sizeof(count));//记录每个点的入度
memset(map,-1,sizeof(map));//邻接表存储图
memset(object,true,sizeof(object));//记录该点是否已访问
memset(repeat,true,sizeof(repeat));//记录该边是否重复
int m,n,s;
scanf("%d %d",&n,&m);
for(int i=0;i<=n;i++)
map[i][0]=1;//记录每个点的出度
while(m--)
{
scanf("%d",&s);
for(int i=0;i<s;i++)
scanf("%d",&a[i]);
for(int i=1;i<s;i++)
for(int j=a[i-1]+1;j<a[i];j++)
for(int k=0;k<s;k++)
if(repeat[a[k]][j])
count[j]++,map[a[k]][map[a[k]][0]++]=j,repeat[a[k]][j]=false;
}
for(int i=1;i<=n;i++)
if(count[i]==0)
array[0][i]=true;
for(m=n,s=0;m>0;s++)
{
for(int i=1;i<=n;i++)
array[s&1^1][i]=false;
for(int i=1;i<=n;i++)
if(array[s&1][i]&&object[i])
{
m--;
object[i]=false;
for(int j=1;j<map[i][0];j++)
{
count[map[i][j]]--;
if(count[map[i][j]]==0)
array[s&1^1][map[i][j]]=true;
}
}
}
printf("%d",s);
return 0;
}


拓扑思路:每次删去当前状态下所有入度为0的点即其所连的边。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: