UVA 10917
题目链接:
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=&problem=1858&mosmsg=Submission+received+with+ID+16031317
题意:
一个图,问有多少种不同的方案从点2走到点1。选路的要求是,对于一条路A-B,若A存在一条路回家比任何从B出发回家的路都短,则可以走该路。
思路:
最短路+DAG_Dp
值得注意的是,A-B不一定是最后构成的最短路上的边。
终于搞清楚大白书上Dijkstra为什么要重复入队列了。因为对于当前节点u,可能下一次遍历时得到更优的距离值d[u],在优先队列中会上升到更前面的位置。这时候就需要把它重复的压到队列里面。这里WA了无数。
然而Bellman-Ford不存在这样的问题,因为它算法设计的本身就会重复入列。自己做的时候把Dijkstra改成Bellman_Ford就过了。
源码:
Dijikstra:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#include <vector>
#include <queue>
#include <stack>
using namespace std;
#define inf (1000000007)
const int MAXN = 1000 + 5;
int n, m;
int head[MAXN], cnt;
struct Edge
{
int v, val;
int ne;
Edge(){}
Edge(int _u, int _v, int _val){v = _v, val = _val, ne = head[_u];}
}edge[MAXN*MAXN*2];
void add_edge(int u, int v, int val)
{
edge[cnt] = Edge(u, v, val);
head[u] = cnt++;
}
struct D
{
int d, u;
bool operator < (const D &rbs)const
{
return d > rbs.d;
}
};
priority_queue<D>que;
int d[MAXN], vis[MAXN];
void dijkstra(int s)
{
for(int i = 1 ; i <= n ; i++)
d[i] = inf, vis[i] = 0;
d[s] = 0;
while(!que.empty()) que.pop();
que.push(D{d[s], s});
while(!que.empty()){
int org = que.top().u; que.pop();
if(vis[org]) continue;
vis[org] = 1;
for(int now = head[org] ; now != -1 ; now = edge[now].ne){
int v = edge[now].v;
if(d[v] > d[org] + edge[now].val){
d[v] = d[org] + edge[now].val;
que.push(D{d[v], v});
}
}
}
}
int dp[MAXN];
void dfs(int u)
{
// printf("u = %d\n", u);
if(dp[u] != -1)
return;
dp[u] = 0;
for(int now = head[u] ; now != -1 ; now = edge[now].ne){
int v = edge[now].v;
if(d[u] > d[v])
dfs(v), dp[u] += dp[v];
}
}
int main()
{
// freopen("UVA 10917.in", "r", stdin);
while(scanf("%d", &n) != EOF && n){
scanf("%d", &m);
int u, v, val;
cnt = 0;
memset(head, -1, sizeof(head));
for(int i = 1 ; i <= m ; i++){
scanf("%d%d%d", &u, &v, &val);
add_edge(u, v, val);
add_edge(v, u, val);
}
dijkstra(2);
for(int i = 1 ;i <= n ; i++)
dp[i] = -1;
dp[2] = 1;
dfs(1);
printf("%d\n", dp[1]);
}
}
Bellman_Ford:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <queue>
#include <cstdlib>
#include <stack>
#include <vector>
using namespace std;
#define MOD (2147483647)
#define LL long long
#define inf (1000000007)
const int MAXN = 1000 + 5;
int head[MAXN], cnt;
struct Edge
{
int u, v, val;
int ne;
Edge(){}
Edge(int _u, int _v, int _val){u = _u, v = _v, val = _val, ne = head[u];}
}edge[MAXN * MAXN * 2];
void addedge(int u, int v, int val)
{
edge[cnt] = Edge(u, v, val);
head[u] = cnt++;
}
int n, m;
int dp[MAXN];
int dis[MAXN];
queue<int>q;
struct D
{
int u;
D(){}
D(int _u){u = _u;}
bool operator < (const D &rbs)const
{
return dis[u] > dis[rbs.u];
}
};
vector<int>path[MAXN], lv[MAXN];
priority_queue<D>que;
int vis[MAXN], in[MAXN];
void dijkstra()
{
memset(in, 0, sizeof(in));
for(int i = 1 ; i <= n ; i++)
dis[i] = inf, path[i].clear();
dis[2] = 0;
in[2] = 1;
while(!que.empty()) que.pop();
que.push(D(2));
while(!que.empty()){
int org = que.top().u; que.pop();
int now = head[org];
in[org] = 0;
while(now != -1){
int u = org;
int v = edge[now].v, val = edge[now].val;
if(dis[v] > dis[u] + val){
// path[v].clear();
// path[v].push_back(u);
dis[v] = dis[u] + val;
if(in[v] == 0) in[v] = 1, que.push(D(v));
}
// else if(dis[v] == dis[u] + val)
// path[v].push_back(u);
now = edge[now].ne;
}
}
// printf("dp\n");
// for(int i = 1 ; i <= n ; i++)
// printf("%d ", dp[i]);
// printf("\n");
// printf("dp\n");
}
void dfs(int u)
{
if(dp[u] != -1)
return;
dp[u] = 0;
for(int now = head[u] ; now != -1 ; now = edge[now].ne){
int v = edge[now].v;
// printf("u = %d, v = %d\n", u, v);
if(dis[v] < dis[u]){
dfs(v); dp[u] += dp[v];
}
}
}
int main()
{
// freopen("UVA 10917.in", "r", stdin);
while(scanf("%d", &n) != EOF && n){
scanf("%d", &m);
cnt = 0;
memset(head, -1, sizeof(head));
int u, v, val;
for(int i = 1 ; i <= m ; i++){
scanf("%d%d%d", &u, &v, &val);
// printf("%d %d %d\n", u, v, val);
addedge(u, v, val);
addedge(v, u, val);
}
dijkstra();
// for(int i = 1 ; i <= n ; i++){
// lv[i].clear();
// in[i] = 0;
// }
// for(int i = 1 ; i <= n ; i++){
// for(int j = 0 ; j < (int)path[i].size() ; j++){
// int u = path[i][j];
// int v = i;
// lv[u].push_back(v);
// in[v]++;
// }
// }
// printf("path\n");
// for(int i = 1 ; i <= n ; i++){
// printf("u = %d, v = ", i);
// for(int j = 0 ; j < (int)lv[i].size() ; j++)
// printf(" %d ", lv[i][j]);
// printf("\n");
// }
// printf("path\nlv\n");
// for(int i = 1 ; i <= n ; i++){
// printf("u = %d, v = ", i);
// for(int j = 0 ; j < (int)lv[i].size() ; j++)
// printf(" %d ", lv[i][j]);
// printf("\n");
// }
// printf("lv\n");
memset(dp, -1, sizeof(dp));
dp[2] = 1;
dfs(1);
printf("%d\n", dp[1]);
}
return 0;
}