您的位置:首页 > 其它

BZOJ 2200 [Usaco2011 Jan]道路和航线

2012-10-01 03:21 351 查看
BZOJ_2200

这个题目一看就知道SPFA可做,但是SPFA就是超时……

USACO上给出的解法的大致意思是:由于每条航线都是单向的,而且不存在从航线的终点辗转到航线起点的通路,那么就是说航线将原图分成了若干个相对封闭的区域,我们把航线从原图中拿掉后,剩下的就应当是若干个连通块。由于每个连通块中只有非负权边,那么我们就可以在连通块内用Dijkstra求最短路了。而且从S开始做最短路时,这些连通块是有一定的拓扑关系的,也就是说只有先确定了S到某些连通块中的点的最短路,才能确定S到另一些连通块中的点的最短路,这样按连通块的拓扑顺序,一个连通块一个连通块的不断地求最短路,就可以得到S到每个点的最短路了。

#include<stdio.h>
#include<string.h>
#include<vector>
#include<queue>
#define MAXD 25010
#define INF 0x3f3f3f3f
struct Edge
{
int v, c;
Edge(){}
Edge(int _v, int _c) : v(_v), c(_c){}
};
std::vector<Edge> road[MAXD], fly[MAXD];
int T, R, P, S;
void init()
{
int x, y, c;
for(int i = 1; i <= T; i ++) road[i].clear(), fly[i].clear();
for(int i = 0; i < R; i ++)
{
scanf("%d%d%d", &x, &y, &c);
road[x].push_back(Edge(y, c)), road[y].push_back(Edge(x, c));

}
for(int i = 0; i < P; i ++)
{
scanf("%d%d%d", &x, &y, &c);
fly[x].push_back(Edge(y, c));
}
}
int p[MAXD], dgr[MAXD], dis[MAXD], cal[MAXD];
struct St
{
int id, v;
St(){}
St(int _id, int _v) : id(_id), v(_v){}
bool operator < (const St &t) const
{
return v > t.v;
}
};
int find(int x)
{
return p[x] == x ? x : (p[x] = find(p[x]));
}
void bfs()
{
memset(dgr, 0, sizeof(dgr[0]) * (T + 1));
std::queue<int> q;
memset(cal, 0, sizeof(cal[0]) * (T + 1));
cal[S] = 1, q.push(S);
while(!q.empty())
{
int x = q.front();
q.pop();
for(int i = 0; i < road[x].size(); i ++)
{
int y = road[x][i].v;
if(!cal[y]) cal[y] = 1, q.push(y);
}
for(int i = 0; i < fly[x].size(); i ++)
{
int y = fly[x][i].v;
++ dgr[find(y)];
if(!cal[y]) cal[y] = 1, q.push(y);
}
}
}
void dij(int set, std::queue<int> &wait, std::vector<int> ini[])
{
std::priority_queue<St> q;
for(int i = 0; i < ini[set].size(); i ++)
{
int x = ini[set][i];
q.push(St(x, dis[x]));
}
while(!q.empty())
{
St st = q.top();
q.pop();
int x = st.id;
if(cal[x]) continue;
cal[x] = 1;
for(int i = 0; i < road[x].size(); i ++)
{
int y = road[x][i].v, c = road[x][i].c;
if(dis[x] + c < dis[y]) dis[y] = dis[x] + c, q.push(St(y, dis[y]));
}
for(int i = 0; i < fly[x].size(); i ++)
{
int y = fly[x][i].v, c = fly[x][i].c, set = find(y);
-- dgr[set];
if(dgr[set] == 0) wait.push(set);
if(dis[x] + c < dis[y]) dis[y] = dis[x] + c, ini[set].push_back(y);
}
}
}
void solve()
{
for(int i = 1; i <= T; i ++) p[i] = i;
for(int i = 1; i <= T; i ++)
for(int j = 0; j < road[i].size(); j ++)
{
int x = find(i), y = find(road[i][j].v);
if(x != y) p[x] = y;
}
bfs();
std::vector<int> ini[MAXD];
std::queue<int> wait;
memset(dis, 0x3f, sizeof(dis[0]) * (T + 1));
dis[S] = 0, ini[find(S)].push_back(S), wait.push(find(S));
memset(cal, 0, sizeof(cal[0]) * (T + 1));
while(!wait.empty())
{
int set = wait.front();
wait.pop();
dij(set, wait, ini);
}
for(int i = 1; i <= T; i ++)
{
if(dis[i] == INF) printf("NO PATH\n");
else printf("%d\n", dis[i]);
}
}
int main()
{
while(scanf("%d%d%d%d", &T, &R, &P, &S) == 4)
{
init();
solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: