SDUT 周赛 2493 A Constructing Roads 最短路
http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2493
题意:
给定一个图,给出起点s,终点e 求从起点到终点的最短距离。这里我们允许从其中任意选择一条路径长度减半(这样的处理只能针对一条边)。
思路:
才开始思路是先求出最短路径,然后取最短路径上的路径的最大权值取一半。结果wa致死。。。后来思考才知道思路错了。
这样不能保证最有,可能由起点到终点的一条不在最短路上的路径直接取半就是最优的。
正确的处理方法是:两遍最短路,分别求出S到所有点的最短路,E到所有点的最短路。然后枚举每条边取半的情况取最小值即可。
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <set> #include <map> #include <string> #define CL(a,num) memset((a),(num),sizeof(a)) #define iabs(x) ((x) > 0 ? (x) : -(x)) #define Min(a,b) (a) > (b)? (b):(a) #define Max(a,b) (a) > (b)? (a):(b) #define ll long long #define inf 0x7f7f7f7f #define MOD 1073741824 #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define test puts("<------------------->") #define maxn 100007 #define M 50007 #define N 1007 using namespace std; //freopen("din.txt","r",stdin); struct node { int v,w; int next; }g[M*2]; int head[N],ct; int dis1[N],dis2[N]; int vt[N]; int n,m; void add(int u,int v,int w) { g[ct].v = v; g[ct].w = w; g[ct].next = head[u]; head[u] = ct++; } void spfa1(int s) { int i; for (i = 1; i <= n; ++i) { dis1[i] = inf; vt[i] = false; } queue<int>q; q.push(s); dis1[s] = 0; vt[s] = true; while (!q.empty()) { int u = q.front(); q.pop(); vt[u] = false; for (i = head[u]; i != -1; i = g[i].next) { int v = g[i].v; int w = g[i].w; if (dis1[v] > dis1[u] + w) { dis1[v] = dis1[u] + w; if (!vt[v]) { vt[v] = true; q.push(v); } } } } } void spfa2(int s) { int i; for (i = 1; i <= n; ++i) { dis2[i] = inf; vt[i] = false; } queue<int>q; q.push(s); dis2[s] = 0; vt[s] = true; while (!q.empty()) { int u = q.front(); q.pop(); vt[u] = false; for (i = head[u]; i != -1; i = g[i].next) { int v = g[i].v; int w = g[i].w; if (dis2[v] > dis2[u] + w) { dis2[v] = dis2[u] + w; if (!vt[v]) { vt[v] = true; q.push(v); } } } } } int main() { //freopen("din.txt","r",stdin); int i,j,x,y,w; while (~scanf("%d%d",&n,&m)) { CL(head,-1); ct = 0; for (i = 0; i < m; ++i) { scanf("%d%d%d",&x,&y,&w); add(x,y,w); add(y,x,w); } int s,e; scanf("%d%d",&s,&e); spfa1(s); if (dis1[e] == inf) { printf("No solution\n"); continue; } spfa2(e); int MIN = inf; for (i = 1; i <= n; ++i) { for (j = head[i]; j != -1; j = g[j].next) { int v = g[j].v; int w = g[j].w; if (dis1[i] != inf && dis2[v] != inf) MIN = min(MIN,dis1[i] + dis2[v] + w/2); if (dis2[i] != inf && dis1[v] != inf) MIN = min(MIN,dis2[i] + dis1[v] + w/2); } } printf("%d\n",MIN); } return 0; }