USACO 2011 Jan Gold 3. Roads and Planes

题意:

给出一个n个结点m条边有向图,可能有负权边;

但是存在负权边a->b则不会有某个路径可以从b到a;

求一个源点s到所有点的最短路(无解输出"NO PATH");

n<=25000,m<=150000;

题解:

高高兴兴的写了一发spfa,O(km)嘛;

然后就TLE了,这题丧心病狂的把spfa卡掉了;

这时候理所当然的想到了dij+heap,写到一半想起来不支持负权边;

所以这个不是一个简单的单源最短路问题;

题中有一个重要条件就是负权边不会回去;

我本以为只是排除了负权环的存在,但是事实上,这个性质使负权边不可能在强连通分量内;

那么每个强连通分量内的最短路可以用dij实现;

强连通分量缩点后是DAG,直接DP传一下进入强连通分量的最短路就可以了;

时间复杂度O(nlogn);

HINT:

每次dij时是没有源点的,直接将所有点加入heap做最短路;

不可到达的强连通分量不能将最短路下传,防止在最后判断是否为inf时错误;

USACO数据还是naive;

为了写这题还去学了dij+heap然后过不了也是醉;

最近写的代码越来越长是错觉吗。。。

代码:

#include<queue>
#include<stack>
#include<vector>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 25500
#define pr pair<int,int>
using namespace std;
vector<int>to[N],val[N],son[N];
priority_queue<pr,vector<pr >,greater<pr > >poq;
queue<int>q;
stack<int>st;
int f[N],dis[N];
int deep[N],low[N],belong[N],in[N],cnt,tot;
bool ins[N],cov[N],vis[N];
void tarjan(int x)
{
	deep[x]=low[x]=++cnt;
	st.push(x),ins[x]=1;
	int i,y;
	for(i=0;i<to[x].size();i++)
	{
		if(!deep[y=to[x][i]])
			tarjan(y),low[x]=min(low[x],low[y]);
		else if(ins[y])
			low[x]=min(low[x],deep[y]);
	}
	if(deep[x]==low[x])
	{
		tot++;
		int k;
		do
		{
			k=st.top(),st.pop();
			ins[k]=0;
			belong[k]=tot;
			son[tot].push_back(k);
		}while(k!=x);
	}
}
void dij(int x)
{
	int i,j,k,y;
	for(i=0;i<son[x].size();i++)
		poq.push(pr(dis[son[x][i]],son[x][i]));
	while(!poq.empty())
	{
		k=poq.top().second;
		poq.pop();
		if(vis[k])	continue;
		vis[k]=1;
		for(i=0;i<to[k].size();i++)
		{
			if(belong[y=to[k][i]]==x)
				if(dis[y]>dis[k]+val[k][i])
				{
					dis[y]=dis[k]+val[k][i];
					poq.push(pr(dis[y],y));
				}
		}
	}
}
int main()
{
	int n,m1,m2,s,i,j,k,x,y,v;
	scanf("%d%d%d%d",&n,&m1,&m2,&s);
	for(i=1;i<=m1;i++)
	{
		scanf("%d%d%d",&x,&y,&v);
		to[x].push_back(y);
		val[x].push_back(v);
		to[y].push_back(x);
		val[y].push_back(v);
	}
	for(i=1;i<=m2;i++)
	{
		scanf("%d%d%d",&x,&y,&v);
		to[x].push_back(y);
		val[x].push_back(v);
	}
	for(i=1;i<=n;i++)
		if(!deep[i])
			tarjan(i);
	for(x=1;x<=n;x++)
	{
		for(i=0;i<to[x].size();i++)
		{
			if(belong[y=to[x][i]]!=belong[x])
			{
				in[belong[y]]++;
			}
		}
	}
	for(i=1;i<=tot;i++)
		if(!in[i])
			q.push(i);
	memset(dis,0x3f,sizeof(dis));
	dis[s]=0,cov[belong[s]]=1;
	while(!q.empty())
	{
		x=q.front(),q.pop();
		if(cov[x])
			dij(x);
		for(j=0;j<son[x].size();j++)
		{
			k=son[x][j];
			for(i=0;i<to[k].size();i++)
			{
				if(belong[y=to[k][i]]!=x)
				{
					if(cov[x])
					{
						cov[belong[y]]=1;
						dis[y]=min(dis[k]+val[k][i],dis[y]);
					}
					in[belong[y]]--;
					if(!in[belong[y]])
						q.push(belong[y]);
				}
			}
		}
	}
	for(i=1;i<=n;i++)
	{
		if(dis[i]==0x3f3f3f3f)
			puts("NO PATH");
		else
			printf("%d\n",dis[i]);
	}
	return 0;
}
时间: 2024-08-05 08:03:17

USACO 2011 Jan Gold 3. Roads and Planes的相关文章

bzoj2581 [USACO 2012 Jan Gold] Cow Run【And-Or Tree】

传送门1:http://www.usaco.org/index.php?page=viewproblem2&cpid=110 传送门2:http://www.lydsy.com/JudgeOnline/problem.php?id=2581 这题我一看就知道自己不会了,只想了个O(2^n * 2 ^ n)即O(2 ^ 2n)的大暴力,也懒得打了,果断看solution. 看了之后惊呆了,看到了一种从未见过,闻所未闻的树叫做And-Or Tree,百度了一下,并没有官方中文翻译,姑且叫他"

【POJ3659】【USACO 2008 Jan Gold】 3.Cell Phone Network 树上最小支配集/贪心 两种做法

题意:求树上最小支配集 最小支配集:点集,即每个点可以"支配"到相邻点,求最少点数可以使所有点被支配. 图上的最小支配集是NP的,但是树上的可以DP做,是O(n)的. 暴力做就好了, f[i]表示此 点被选时的子树全支配的最小代价 g[i]表示其父亲节 点被选时的子树全支配的最小代价 h[i]表示其某子节 点被选时的子树全支配的最小代价 然后暴力转移. (v是子节点) f[x]=∑(min(f[v],min(g[v],h[v])))+1; g[x]=∑(min(f[v],h[v]));

[USACO 2011 Dec Gold] Threatening Letter【后缀】

Problem 3: Threatening Letter [J. Kuipers, 2002] FJ has had a terrible fight with his neighbor and wants to send him a nasty letter, but wants to remain anonymous. As so many before him have done, he plans to cut out printed letters and paste them on

【POJ3657】【USACO 2008 Jan Gold】 1.Haybale Guessing 二分答案,并查集check

题意: 输入n.m表示数列长度为n,有m条有序的限制{l,r,x}. 限制:l~r间所有数最小值为x. 问到第几条限制开始出现矛盾,都不出现输出"0". 题解: 首先这题比较厉害,正常解有点难,不妨转化成二分答案. 我们二分"答案",也就是第ans条出现矛盾. 考虑到若一条限制S所在区间被另一个限制Seg包含,且Seg这条限制的x又比S.x大, 那么也就是意为 ① [Seg.l,Seg.r]间最小值为Seg.x ② [S  .l,S  .r]间最小值为S  .x ③

【POJ3658】【USACO 2008 Jan Gold】 2.Artificial Lake人工湖 单调栈

人工湖 Time Limit: 1 Sec  Memory Limit: 128 MB Description 夏日那让人喘不过气的酷热将奶牛们的烦躁情绪推到了最高点.最终,FJ 决定建一个人工湖供奶牛消暑之用.为了使湖看起来更加真实,FJ决定将湖的 横截面建成N(1 <= N <= 100,000)个连续的平台高低错落的组合状,所有的平台 从左到右按1..N依次编号.当然咯,在湖中注入水后,这些平台都将被淹没. 平台i在设计图上用它的宽度W_i(1 <= W_i <= 1,000

USACO翻译:USACO 2012 JAN三题(1)

USACO 2012 JAN(题目一) 一.题目概览 中文题目名称 礼物 配送路线 游戏组合技 英文题目名称 gifts delivery combos 可执行文件名 gifts delivery combos 输入文件名 gifts.in delivery.in combos.in 输出文件名 gifts.out delivery.out combos.out 每个测试点时限 1秒 1秒 1秒 测试点数目 10 10 10 每个测试点分值 10 10 10 比较方式 全文比较 全文比较 全文比

USACO翻译:USACO 2013 JAN三题(1)

USACO 2013 JAN 一.题目概览 中文题目名称 镜子 栅栏油漆 奶牛排队 英文题目名称 mirrors paint lineup 可执行文件名 mirrors paint lineup 输入文件名 mirrors.in paint.in lineup.in 输出文件名 mirrors.out paint.out lineup.out 每个测试点时限 1秒 1秒 1秒 测试点数目 10 10 10 每个测试点分值 10 10 10 比较方式 全文比较 全文比较 全文比较 二.运行内存限制

USACO翻译:USACO 2014 JAN三题(2)

USACO 2014 JAN 一.题目概览 中文题目名称 队伍平衡 滑雪录像 滑雪场建设 英文题目名称 bteams recording skicourse 可执行文件名 bteams recording skicourse 输入文件名 bteams.in recording.in skicourse.in 输出文件名 bteams.out recording.out skicourse.out 每个测试点时限 1秒 1秒 1秒 测试点数目 10 10 10 每个测试点分值 10 10 10 比

USACO翻译:USACO 2012 JAN三题(2)

USACO 2012 JAN(题目二) 一.题目概览 中文题目名称 叠干草 分干草 奶牛跑步 英文题目名称 stacking baleshare cowrun 可执行文件名 stacking baleshare cowrun 输入文件名 stacking.in baleshare.in cowrun.in 输出文件名 stacking.out baleshare.out cowrun.out 每个测试点时限 1秒 1秒 1秒 测试点数目 10 10 10 每个测试点分值 10 10 10 比较方