[Usaco2011 Jan]道路和航线
2013-11-21 18:43
267 查看
Farmer John正在一个新的销售区域对他的牛奶销售方案进行调查。他想把牛奶送到T个城镇 (1 <= T <= 25,000),编号为1T。这些城镇之间通过R条道路 (1 <= R <= 50,000,编号为1到R) 和P条航线 (1 <= P <= 50,000,编号为1到P) 连接。每条道路i或者航线i连接城镇A_i (1 <= A_i <= T)到B_i (1 <= B_i <= T),花费为C_i。对于道路,0 <= C_i <= 10,000;然而航线的花费很神奇,花费C_i可能是负数(-10,000
<= C_i <= 10,000)。道路是双向的,可以从A_i到B_i,也可以从B_i到A_i,花费都是C_i。然而航线与之不同,只可以从A_i到B_i。事实上,由于最近恐怖主义太嚣张,为了社会和谐,出台 了一些政策保证:如果有一条航线可以从A_i到B_i,那么保证不可能通过一些道路和航线从B_i回到A_i。由于FJ的奶牛世界公认十分给力,他需要运送奶牛到每一个城镇。他想找到从发送中心城镇S(1 <= S <= T) 把奶牛送到每个城镇的最便宜的方案,或者知道这是不可能的。
这题又是比较贱的卡了SPFA。。
改DIJ后你就会发现。。 dij不能写有负边得题啊。
不过题目中有个重要的条件
如果有一条航线可以从A_i到B_i,那么保证不可能通过一些道路和航线从B_i回到A_i
这个条件很重要
如果我们把整个图缩点之后,就会发现,这种负边一定是连接着不同的两个连通块!
那么我们就可以在每个连通块内进行dijkstra了
然后就会发现需要进行拓扑排序才行。
然后我就不知道为啥wa了一天。。估计写的太乱了
我的方法是这样。
首先将整个图缩点。
然后把从源点到达不了的边都给干掉。
这样是方便我们拓扑排序用的。
然后把源点所在的联通块编号插入到队列中,开始拓扑排序。
拓扑过程中每次都要进行dijkstra,将某个联通块内的最短路求出来
我们用一些vector记录每个联通块中从别的连通块可以连边进来的点。
那么每次dijkstra时,就用这些点作为初始状态进行扩展
求完dijkstra后就开始删边,找下一个拓扑序列中的连通块, 同时更新每个联通块中从别的连通块可以连边进来的点。
<= C_i <= 10,000)。道路是双向的,可以从A_i到B_i,也可以从B_i到A_i,花费都是C_i。然而航线与之不同,只可以从A_i到B_i。事实上,由于最近恐怖主义太嚣张,为了社会和谐,出台 了一些政策保证:如果有一条航线可以从A_i到B_i,那么保证不可能通过一些道路和航线从B_i回到A_i。由于FJ的奶牛世界公认十分给力,他需要运送奶牛到每一个城镇。他想找到从发送中心城镇S(1 <= S <= T) 把奶牛送到每个城镇的最便宜的方案,或者知道这是不可能的。
这题又是比较贱的卡了SPFA。。
改DIJ后你就会发现。。 dij不能写有负边得题啊。
不过题目中有个重要的条件
如果有一条航线可以从A_i到B_i,那么保证不可能通过一些道路和航线从B_i回到A_i
这个条件很重要
如果我们把整个图缩点之后,就会发现,这种负边一定是连接着不同的两个连通块!
那么我们就可以在每个连通块内进行dijkstra了
然后就会发现需要进行拓扑排序才行。
然后我就不知道为啥wa了一天。。估计写的太乱了
我的方法是这样。
首先将整个图缩点。
然后把从源点到达不了的边都给干掉。
这样是方便我们拓扑排序用的。
然后把源点所在的联通块编号插入到队列中,开始拓扑排序。
拓扑过程中每次都要进行dijkstra,将某个联通块内的最短路求出来
我们用一些vector记录每个联通块中从别的连通块可以连边进来的点。
那么每次dijkstra时,就用这些点作为初始状态进行扩展
求完dijkstra后就开始删边,找下一个拓扑序列中的连通块, 同时更新每个联通块中从别的连通块可以连边进来的点。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <queue> #include <stack> #define MAXN 55555 #define INF 1000010080 using namespace std; typedef pair<int, int> P; priority_queue<P, vector<P>, greater<P> > q; vector<P> g[MAXN]; int dis[MAXN], vis[MAXN], cango[MAXN]; int src, n, R, m; int scc, ind; int dfn[MAXN], instack[MAXN], low[MAXN], fa[MAXN], in[MAXN], last[MAXN], num[MAXN], c[MAXN]; stack<int>st; vector<int>bl[MAXN], got[MAXN]; void tarjan(int u) { dfn[u] = low[u] = ++ind; st.push(u); instack[u] = 1; int sz = g[u].size(); for(int i = 0; i < sz; i++) { int v = g[u][i].first; if(!dfn[v]) { tarjan(v); low[u] = min(low[u], low[v]); } else if(instack[v]) low[u] = min(low[u], dfn[v]); } if(dfn[u] == low[u]) { scc++; while(true) { int tmp = st.top(); st.pop(); instack[tmp] = 0; fa[tmp] = scc; bl[scc].push_back(tmp); if(tmp == u) break; } } } int que[MAXN]; int l, r; void dij(int now) { while(!q.empty()) q.pop(); for(int i = 0; i < got[now].size(); i++) { int u = got[now][i]; q.push(P(dis[u], u)); } while(!q.empty()) { P p = q.top(); q.pop(); int u = p.second, d = p.first; if(vis[u]) continue; vis[u] = 1; int sz = g[u].size(); for(int i = 0; i < sz; i++) { int v = g[u][i].first; int w = g[u][i].second; if(fa[v] == fa[u]) { if(d + w < dis[v]) { dis[v] = d + w; q.push(P(dis[v], v)); } } } } } void dfs(int u) { cango[u] = 1; int sz = g[u].size(); for(int i = 0; i < sz; i++) { int v = g[u][i].first; if(!cango[v]) dfs(v); } } void gao() { que[r++] = fa[src]; while(l < r) { int now = que[l++]; dij(now); int sz = bl[now].size(); for(int i = 0; i < sz; i++) { int u = bl[now][i]; for(int j = 0; j < g[u].size(); j++) { int v = g[u][j].first; int w = g[u][j].second; if(fa[v] != now) { --in[fa[v]]; if(dis[u] + w < dis[v]) dis[v] = dis[u] + w, got[fa[v]].push_back(v); if(in[fa[v]] == 0) que[r++] = fa[v]; } } } } } int main() { int u, v, w; scanf("%d%d%d%d", &n, &R, &m, &src); for(int i = 1; i <= n; i++) dis[i] = INF; dis[src] = 0; for(int i = 0; i < R; i++) { scanf("%d%d%d", &u, &v, &w); g[u].push_back(P(v, w)); g[v].push_back(P(u, w)); } for(int i = 0; i < m; i++) { scanf("%d%d%d", &u, &v, &w); g[u].push_back(P(v, w)); } for(int i = 1; i <= n; i++) if(!dfn[i]) tarjan(i); got[fa[src]].push_back(src); dfs(src); for(int i = 1; i <= n; i++) { if(!cango[i]) continue; int sz = g[i].size(); for(int j = 0; j < sz; j++) { v = g[i][j].first; if(fa[v] != fa[i]) in[fa[v]]++; } } gao(); for(int i = 1; i <= n; i++) { if(dis[i] == INF) printf("NO PATH\n"); else printf("%d\n", dis[i]); } return 0; }
相关文章推荐
- BZOJ 2200: [Usaco2011 Jan]道路和航线
- bzoj2200 [Usaco2011 Jan]道路和航线 最短路
- 【BZOJ】【2200】【USACO 2011 Jan】道路和航线
- BZOJ 2200 [Usaco2011 Jan]道路和航线
- BZOJ2200: [Usaco2011 Jan]道路和航线
- bzoj 2200: [Usaco2011 Jan]道路和航线——拓扑+dijkstra
- [BZOJ2200][Usaco2011 Jan]道路和航线
- 【BZOJ】2200: [Usaco2011 Jan]道路和航线
- bzoj 2200: [Usaco2011 Jan]道路和航线【spfa】
- 【BZOJ2199】【Usaco2011 Jan】奶牛议会
- [BZOJ2199][Usaco2011 Jan][2-SAT]奶牛议会
- BZOJ 2199: [Usaco2011 Jan]奶牛议会
- 【BZOJ2199】 [Usaco2011 Jan]奶牛议会
- [USACO 2011Jan Gold]道路与航线
- 2199: [Usaco2011 Jan]奶牛议会 2-SAT
- bzoj 2199: [Usaco2011 Jan]奶牛议会
- BZOJ2199: [Usaco2011 Jan]奶牛议会(2-SAT)
- 【BZOJ2199】[Usaco2011 Jan]奶牛议会 2-SAT
- BZOJ 2199: [Usaco2011 Jan]奶牛议会 2-sat
- bzoj2199 [Usaco2011 Jan]奶牛议会 2-SAT