这题是先跑一个最短路,找最短路中最短的边的个数假设为A,那么第二问的答案为M-A,然后根据最短路的建图,求最小割,也就是把最短路的图建权值为1的边,跑一个最大流,注意重边不要删,因为比赛的时候问的,重边不删。
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <queue>
#include <math.h>
#define maxn 2000
#define maxm 60000
#define qq 200000
#define inf 1000000005
#define mem(a, b) memset(a, b, sizeof(a))
using namespace std;
int heads[maxn + 5], heads2[maxn + 5], que[qq + 5], sizes, sizes2, dp[maxn + 5], dis[maxn + 5], p[maxn + 5], f[maxn + 5][maxn + 5], d[maxn + 5], num[maxn + 5], counts, n, m, mi, ans1, ans2, source, sink;
bool vis[maxn + 5];
struct edge
{
int v, w, next;
}eg[maxm * 2 + 5], eg2[maxm * 2 + 5];
struct node
{
int v, t, dis;
};
void inits()
{
mem(vis, 0);
mem(heads, -1);
mem(heads2, -1);
mem(num, 0);
sizes = 0;
sizes2 = 0;
counts = 0;
return;
}
void add(int u, int v, int w)
{
eg[sizes].v = v;
eg[sizes].w = w;
eg[sizes].next = heads[u];
heads[u] = sizes++;
return;
}
void add2(int u, int v)
{
eg2[sizes2].v = v;
eg2[sizes2].w = 1;
eg2[sizes2].next = heads2[u];
heads2[u] = sizes2++;
eg2[sizes2].v = u;
eg2[sizes2].w = 0;
eg2[sizes2].next = heads2[v];
heads2[v] = sizes2++;
return;
}
void spfa()
{
mem(vis, 0);
int top = 0, ta = 0;
for(int i = 2;i <= n;i++)
dis[i] = dp[i] = inf;
dis[1] = 0;
vis[1] = 0;
dp[1] = 0;
que[top++] = 1;
while(ta != top)
{
int u = que[ta++];
ta %= qq;
for(int i = heads[u];i != -1;i = eg[i].next)
{
int v = eg[i].v;
int w = eg[i].w;
if(dis[v] > dis[u] + w)
{
dis[v] = dis[u] + w;
dp[v] = dp[u] + 1;
if(!vis[v])
{
vis[v] = 1;
que[top++] = v;
top %= qq;
}
}
else if(dis[v] == dis[u] + w)
{
dp[v] = min(dp[v], dp[u] + 1);
if(!vis[v])
{
vis[v] = 1;
que[top++] = v;
top %= qq;
}
}
}
vis[u] = 0;
}
ans1 = m - dp[n];
return;
}
void build()
{
for(int i = 1;i <= n;i++)
{
for(int j = heads[i];j != -1;j = eg[j].next)
{
int v = eg[j].v;
int w = eg[j].w;
if(dis[v] - dis[i] == w)
add2(i, v);
}
}
return;
}
void bfs()
{
mem(vis, 0);
d[n] = 0;
num[d[n]]++;
int top = 0, ta = 0;
vis[n] = 1;
que[top++] = n;
while(top != ta)
{
int u = que[ta++];
ta %= qq;
for(int i = heads2[u];i != -1;i = eg2[i].next)
{
int v = eg2[i].v;
if(!vis[v])
{
vis[v] = 1;
d[v] = d[u] + 1;
num[d[v]]++;
que[top++] = v;
top %= qq;
}
}
}
return;
}
int dfs(int a,int cost)
{
if(a == sink)
return cost;
int mins = n - 1, lv = cost, dd;
for(int i = heads2[a];i != -1;i = eg2[i].next)
{
int v = eg2[i].v;
int w = eg2[i].w;
if(w)
{
if(d[v] + 1 == d[a])
{
if(lv < eg2[i].w)
dd = lv;
else
dd = eg2[i].w;
dd = dfs(v, dd);
eg2[i].w -= dd;
eg2[i^1].w += dd;
lv -= dd;
if(d[source] >= n)
return cost - lv;
if(!lv)
break;
}
if(d[v] < mins)
mins = d[v];
}
}
if(lv == cost)
{
--num[d[a]];
if(num[d[a]] == 0)
d[source] = n;
d[a] = mins + 1;
++num[d[a]];
}
return cost - lv;
}
int isap()
{
source = 1;
sink = n;
int ff = 0, st = source;
while(d[st] < n)
ff += dfs(st, inf);
return ff;
}
int main(int argc, char *argv[])
{
int a, b, c;
while(~scanf("%d%d", &n, &m))
{
inits();
for(int i = 0;i < m;i++)
{
scanf("%d%d%d", &a, &b, &c);
add(a, b, c);
add(b, a, c);
}
spfa();
build();
bfs();
ans2 = isap();
printf("%d %d\n", ans2, ans1);
}
return 0;
}