题意:
给一个无向图,问从1号点到N号点是否存在两条或以上没有公共边的最短路,如果存在输出路径,否则输出无解。
思路:
先求一次最短路,那么对于dis[j]=dis[i]+w[i][j] 的边w[i][j] 则一定在最短路上,那么在网络上建边i->j,流量为1,如果最后最大流大于等于2即满足题意,然后找有流的边dfs找解即可。要注意的是这道题的内存限制是4096KB,在大内存的时代,这么严格的内存要求已经很少见了。。。用的是GZ大牛的Dinic,要比一般的dinic多一个数组,各种MLE,后来改了spfa的写法后终于过了。
贴上挫代码一份:
#include<cstdio>
#include<string>
#include<cmath>
#include<queue>
#include<vector>
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxnode = 401 + 5;
const int maxedge = 401 * 401 * 2 + 10;
const int oo = 100000000;
struct Dinic
{
int node, src, dest, nedge;
int head[maxnode], next[maxedge];
short point[maxedge];
short flow[maxedge], capa[maxedge];
short dist[maxnode], Q[maxnode];
int work[maxnode];
vector<short>path[2];
int sum;
void init (int _node, int _src, int _dest)
{
path[0].clear();
path[1].clear();
node = _node;
src = _src;
dest = _dest;
for (int i = 0; i < node; i++) head[i] = -1;
nedge = 0;
}
void addedge (short u, short v, short c1, short c2)
{
point[nedge] = v, capa[nedge] = c1, flow[nedge] = 0, next[nedge] = head[u], head[u] = (nedge++);
point[nedge] = u, capa[nedge] = c2, flow[nedge] = 0, next[nedge] = head[v], head[v] = (nedge++);
}
bool dinic_bfs()
{
memset (dist, -1, sizeof (dist) );
dist[src] = 0;
int sizeQ = 0;
Q[sizeQ++] = src;
for (int cl = 0; cl < sizeQ; cl++)
for (int k = Q[cl], i = head[k]; i >= 0; i = next[i])
if (flow[i] < capa[i] && dist[point[i]] < 0)
{
dist[point[i]] = dist[k] + 1;
Q[sizeQ++] = point[i];
}
return dist[dest] >= 0;
}
int dinic_dfs (int x, int exp)
{
if (x == dest) return exp;
for (int &i = work[x]; i >= 0; i = next[i])
{
short v = point[i], tmp;
if (flow[i] < capa[i] && dist[v] == dist[x] + 1 && (tmp = dinic_dfs (v, min (exp, capa[i] - flow[i]) ) ) > 0)
{
flow[i] += tmp;
flow[i ^ 1] -= tmp;
return tmp;
}
}
return 0;
}
int dinic_flow()
{
int result = 0;
while (dinic_bfs() )
{
for (int i = 0; i < node; i++) work[i] = head[i];
while (1)
{
int delta = dinic_dfs (src, oo);
if (delta == 0) break;
result += delta;
}
}
return result;
}
void path_dfs (int x)
{
if (x == dest) return;
path[sum].push_back (x);
for (int i = head[x]; i >= 0; i = next[i])
{
//printf("^^^%d %d %d\n",x,point[i],flow[i]);
if (flow[i] >= 1)
{
flow[i] = 0;
path_dfs (point[i]);
break;
}
}
}
void get_res()
{
//printf("@@@%d\n",dest);
sum = 0;
for (int i = head[1]; i >= 0; i = next[i])
{
if (flow[i] >= 1)
{
path[sum].push_back (1);
path_dfs (point[i]);
sum++;
}
if (sum >= 2) break;
}
}
void output()
{
// printf ("@@@%d %d %d\n", (int) path[0].size(),(int) path[1].size() ,sum);
printf ("%d", path[0][0]);
for (int i = 1; i < (int) path[0].size() ; i++)
{
printf (" %d", path[0][i]);
}
printf ("\n");
printf ("%d", path[1][0]);
for (int i = 1; i < (int) path[1].size() ; i++)
{
printf (" %d", path[1][i]);
}
printf ("\n");
}
void show()
{
for (int k = 0; k <= dest; k++)
{
for (int i = head[k]; i >= 0; i = next[i])
{
printf ("$$$%d %d %d\n", k, point[i], flow[i]);
}
}
}
} Solver;
//
//
//#define INF 100000000
//void spfa (int n, int s) //这种spfa的写法容易超内存
//{
// for (int i = 1; i <= n; ++i)
// d[i] = INF;
// memset (mark, false , sizeof (mark) );
// d[s] = 0;
// while (Q.size() ) Q.pop();
// Q.push (s);
// mark[s] = true;
// while (Q.size() )
// {
// int k = Q.front();
// Q.pop();
// mark[k] = false;
// for (int i = 0; i < adj[k].size(); ++i, ++i)
// {
// int s = adj[k][i];
// int w = adj[k][i + 1];
// if (d[k] + w < d[s])
// {
// d[s] = d[k] + w;
// if (mark[s] == 0)
// {
// mark[s] = true;
// Q.push (s);
// }
// }
// }
// }
// return;
//}
int N, M, x, y, l;
#define INF 10000000
#define MAX 401
#define LMT 401
int dis[MAX];
bool vis[MAX];
short g[MAX][MAX];
short q[MAX];
int spfa (short s, short t)
{
short i, j, head, tail;
head = tail = 0;
memset (vis, 0, sizeof (vis) );
for (i = 1; i <= N; i++) dis[i] = INF;
dis[s] = 0;
vis[s] = true;
q[tail++] = s;
while (head != tail)
{
i = q[head];
head = (head + 1) % LMT;
vis[i] = 0;
for (j = 1; j <= N; j++)
if (g[i][j] != -1 && dis[j] > dis[i] + g[i][j])
{
dis[j] = dis[i] + g[i][j];
if (0 == vis[j])
{
vis[j] = 1;
q[tail] = j;
tail = (tail + 1) % LMT;
}
}
}
return dis[t] < INF;
}
int main()
{
#ifdef untitled1
freopen ("in.in", "r", stdin);
#endif // untitled1
scanf ("%d%d", &N, &M);
memset (g, -1, sizeof (g) );
for (int i = 1; i <= M; i++)
{
scanf ("%d%d%d", &x, &y, &l);
// adj[x].push_back ( (short) y);
// adj[x].push_back ( (short) l);
// adj[y].push_back ( (short) x);
// adj[y].push_back ( (short) l);
g[x][y] = (short) l;
g[y][x] = (short) l;
}
spfa (1, N);
Solver.init (N + 2, 0, N + 1);
Solver.addedge (0, 1, 2, 0);
Solver.addedge (N, N + 1, 2, 0);
for (int i = 1; i <= N; i++)
{
for (int j = 1; j <= N; j++)
{
if (g[i][j] != -1 && dis[j] == dis[i] + g[i][j])
{
Solver.addedge (i, j, 1, 0);
}
}
}
int res = Solver.dinic_flow();
//Solver.show();
//printf ("~~~%d\n", res);
if (res >= 2)
{
Solver.get_res();
Solver.output();
}
else
{
printf ("No solution\n");
}
return 0;
}