AcDream 1415 Important Roads 解题报告(最短路 + 线段树)
2014-10-04 19:27
363 查看
Important Roads
Special JudgeTime Limit: 20000/10000MS (Java/Others)MemoryLimit: 128000/64000KB (Java/Others)
SubmitStatisticNext
Problem
Problem Description
The city where Georgie lives has n junctions some of which are connected by bidirectional roads.Every day Georgie drives from his home to work and back. But the roads in the city where Georgie lives are very bad, so they are very often closed for repair. Georgie noticed that
when some roads are closed he still can get from home to work in the same time as if all roads were available.
But there are such roads that if they are closed for repair the time Georgie needs to get from home to work increases, and sometimes Georgie even cannot get to work by a car any more. Georgie calls such roads
important.
Help Georgie to find all important roads in the city.
Input
The first line of the input file contains n and m — the number of junctions and roads in the city where Georgie lives, respectively (2 ≤ n ≤ 20 000, 1 ≤ m ≤ 100 000). Georgie lives at the junction 1 and works atthe junction n.
The following m lines contain information about roads. Each road is specified by the junctions it connects and the time Georgie needs to drive along it. The time to drive along the road is positive and doesn’t exceed
100 000. There can be several roads between a pair of junctions, but no road connects a junction to itself. It is guaranteed that if all roads are available, Georgie can get from home to work.
Output
Output l — the number of important roads — at the first line of the output file. The second line must contain l numbers, the numbers of important roads. Roads are numbered from 1 to m as they are given in the input file.
Sample Input
6 7 1 2 1 2 3 1 2 5 3 1 3 2 3 5 1 2 4 1 5 6 2
Sample Output
2 5 7
解题报告: 队友说这题是求最短路,然后求桥。
当然,图论我不太熟,比赛的时候直接用最短路和线段树做了。
首先求出每个点到起点的最短距离,到终点的最短距离。然后如果dis(sta, u) + len(u, v) + dis(v, end) = shortPath,那么我们可以确定这条边在最短路上。
接下来我们要确定u,v这段路径是否是重要的。如果重要,那么从dis(sta, u)开始,到dis(sta, v),这段路必然是唯一的。如果中间有其他重复覆盖了,那么这两条路都不是重要的。我们用线段树完成这个操作。因为距离比较大,所以需要离散化处理。当u,v这条边覆盖了[a, b]这段路程时,我们在线段树上将[a, b-1]区间置为这条边的id。第二次我们判断[a, b-1]是否都是被置为这条边的id,如果不是,那么这条边就不是重要的。
代码如下:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <iomanip>
#include <cassert>
using namespace std;
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define ff(i, n) for(int i=0;i<(n);i++)
#define fff(i, n, m) for(int i=(n);i<=(m);i++)
#define dff(i, n, m) for(int i=(n);i>=(m);i--)
#define travel(e, u) for(int e = u, v = vv[u]; e; e = nxt[e], v = vv[e])
#define bit(n) (1LL<<(n))
#define clr(a, b) memset((a), b, sizeof(a))
typedef long long LL;
typedef unsigned long long ULL;
void work();
int main()
{
#ifdef ACM
freopen("in.txt", "r", stdin);
#endif // ACM
work();
return 0;
}
void scanf(int & x, char ch = 0)
{
while((ch=getchar()) < '0' || ch > '9');
x = ch - '0';
while((ch=getchar()) >= '0' && ch <= '9') x = x * 10 + ch - '0';
}
/***************************************************************************************/
const int maxv = 20010;
const int maxe = 200010;
int n, m;
int edge[maxv], ecnt;
int nxt[maxe], vv[maxe], ww[maxe], eid[maxe];
int dSta[maxv], dEnd[maxv];
bool vis[maxv];
bool evis[maxe];
int g[maxe];
int pos[maxv];
int ma[maxv << 2];
int mi[maxv << 2];
int co[maxv << 2];
void init()
{
ecnt = 2;
clr(edge, 0);
}
void addEdge(int u, int v, int w, int id, int first[])
{
nxt[ecnt] = first[u], vv[ecnt] = v, ww[ecnt] = w, eid[ecnt] = id, first[u] = ecnt++;
}
struct Node
{
int u, d;
Node(int u = 0, int d = 0) : u(u), d(d) {}
bool operator<(const Node & cmp) const
{
return d > cmp.d;
}
} x, y;
void getShortPath(int sta, int arr[])
{
clr(vis, 0);
priority_queue<Node> que;
que.push(Node(sta, 0));
while(que.size())
{
x = que.top();
que.pop();
if(vis[x.u]) continue;
vis[x.u] = true, arr[x.u] = x.d;
travel(e, edge[x.u]) if(!vis[v])
que.push(Node(v, x.d + ww[e]));
}
}
#define lson l, m, pos<<1
#define rson m+1, r, pos<<1|1
#define ls (pos<<1)
#define rs (pos<<1|1)
#define mid ((l+r)/2)
#define rt 0, tot, 1
void updateFather(int pos)
{
ma[pos] = max(ma[ls], ma[rs]);
mi[pos] = min(mi[ls], mi[rs]);
}
void updateSon(int pos)
{
if(co[pos])
{
co[ls] = ma[ls] = mi[ls] = co[pos];
co[rs] = ma[rs] = mi[rs] = co[pos];
co[pos] = 0;
}
}
void update(int L, int R, int v, int l, int r, int pos)
{
if(L<=l && r<=R)
{
co[pos] = ma[pos] = mi[pos] = v;
return;
}
updateSon(pos);
int m = mid;
if(L<=m) update(L, R, v, lson);
if(m <R) update(L, R, v, rson);
updateFather(pos);
}
int Mi, Ma;
void qry(int L, int R, int l, int r, int pos)
{
if(L<=l && r<=R)
{
Mi = min(Mi, mi[pos]);
Ma = max(Ma, ma[pos]);
return;
}
updateSon(pos);
int m = mid;
int ret = 0;
if(L<=m) qry(L,R,lson);
if(m< R) qry(L,R,rson);
}
void work()
{
while(scanf("%d%d", &n, &m) == 2)
{
init();
fff(i, 1, m)
{
int u, v, w;
scanf(u), scanf(v), scanf(w);
addEdge(u, v, w, i, edge);
addEdge(v, u, w, i, edge);
}
getShortPath(1, dSta);
getShortPath(n, dEnd);
int shrt = dEnd[1];
int tot = 0;
fff(i, 1, n)
g[tot++] = dSta[i];
sort(g, g + tot);
tot = unique(g, g + tot) - g;
fff(i, 1, n)
pos[i] = lower_bound(g, g+tot, dSta[i]) - g;
clr(ma, 0);
clr(mi, 0x7f);
clr(co, 0);
clr(evis, 0);
fff(u, 1, n)
{
travel(e, edge[u]) if(u != v && dSta[u] + ww[e] == shrt - dEnd[v])
{
int L = pos[u];
int R = pos[v] - 1;
evis[eid[e]] = true;
update(L, R, eid[e], 0, tot, 1);
}
}
fff(u, 1, n)
{
travel(e, edge[u]) if(u != v && dSta[u] + ww[e] == shrt - dEnd[v])
{
int L = pos[u];
int R = pos[v] - 1;
Ma = 0, Mi = 0x7f7f7f7f;
qry(L, R, 0, tot, 1);
if(Ma != eid[e] || Mi != eid[e])
evis[eid[e]] = false;
update(L, R, eid[e], 0, tot, 1);
}
}
int ans = 0;
fff(i, 1, m) if(evis[i])
g[ans++] = i;
printf("%d\n", ans);
if(ans) printf("%d", g[0]);
fff(i, 1, ans-1) printf(" %d", g[i]);
puts("");
}
}
相关文章推荐
- BZOJ 4720 [Noip 2016] 期望DP+最短路 解题报告
- HDOJ 1251 统计难题——第二次用字典树AC题目,写一下解题报告
- poj 2777 count color解题报告【线段树】
- HDOJ 2037:今年暑假不AC 解题报告
- luogu解题报告:P1119灾后重建【图论/最短路】
- HDU2544 最短路 解题报告--Dijkstra
- HDU 4578 Transformation 解题报告(线段树,2013杭州邀请赛)
- ACdream 1415 Important Roads(最短路&缩点&找桥)
- BZOJ 2733 [HNOI 2012] 线段树合并 解题报告
- poj 2449 Remmarguts' Date 第k短路 A*+spfa 解题报告
- Hdu 1754 I Hate It 线段树 解题报告
- csu 1321 CX and girls 最短路 解题报告
- 【HDU4313】 - Matrix - 树状DP Version 思路+解题报告+AC代码【0.4%达成】
- csu 1110 RMQ with Shifts(线段树) 解题报告
- 线段树 划分树 合并树 解题报告
- POJ 4047 Garden (线段树 - 区间增减、区间查询) -- 解题报告
- poj 3368 Frequent values解题报告【线段树】
- HDU 5209 Relief grain 解题报告(树链剖分 + 线段树)
- SDUT 3513 皮卡丘的梦想 (二进制+线段树) -- 解题报告
- 2017.9.28 线段树永久标记 解题报告