题目大题:
求最多拆几条边图的1 -> n的最小距离不会变
求最少拆几条边图的1 -> n的最小距离会变
最短路 + 网络流的问题
求出最短路径图(包含所有最短路径的图) 之后用m - (拥有最少边数的最短路径) 得到一个解
之后将最短路径图中的边重新建图(流量为1)求最大流
感觉写的比较麻烦,时间也正好卡着过的。
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 2005;
const int INF = 2000000000;
struct W{
int u,v,dist;
W(int u,int v,int dist):u(u),v(v),dist(dist){};
};
struct Edge{
int to,dist;
Edge(int to = 0,int dist = 0):to(to),dist(dist){};
};
struct State{
int pos,dist,num;
State(int pos,int dist = 0,int num = 0):pos(pos),dist(dist),num(num){};
friend bool operator < (State p,State q){
if(p.dist != q.dist)
return p.dist > q.dist;
else
return p.num > q.num;
}
};
vector<W>edge;
//------------------------BFS最短路------------------------------------------
vector<Edge>G[maxn];
int n,m,vis[maxn];
int dist[maxn];
int min_dist,min_num;
int ans1,ans2;
void bfs(){
min_dist = -1;
min_num = -1;
priority_queue<State>q;
memset(dist,-1,sizeof(dist));
q.push(State(1,0,0));
while(!q.empty()){
State now = q.top(); q.pop();
if(vis[now.pos]) continue;
dist[now.pos] = now.dist;
if(now.pos == n){
min_dist = now.dist;
min_num = now.num;
}
vis[now.pos] = 1;
for(int i = 0; i < G[now.pos].size(); i++){
int to = G[now.pos][i].to;
int dist = G[now.pos][i].dist;
q.push(State(to,now.dist + dist,now.num + 1));
}
}
}
//----------------------------最大流--------------------------------------
struct W_Edge{
int from,to,flow,cap;
W_Edge(int from,int to,int flow,int cap):from(from),to(to),flow(flow),cap(cap){};
};
struct EdmondsKarp{;
vector<W_Edge>w_edges;
vector<int>w_G[maxn];
int n,m;
int a[maxn]; //起点到i的可改进量
int p[maxn];
void init(){
w_edges.clear();
for(int i = 0; i < maxn; i++) w_G[i].clear();
}
void add(int u,int v,int cap){
w_edges.push_back(W_Edge(u,v,0,cap));
w_edges.push_back(W_Edge(v,u,0,0));
int m = w_edges.size();
w_G[u].push_back(m - 2);
w_G[v].push_back(m - 1);
}
int Maxflow(int s,int t){
int flow = 0;
for(;;){
memset(a,0,sizeof(a));
queue<int>Q;
Q.push(s);
a[s] = INF;
while(!Q.empty()){
int x = Q.front(); Q.pop();
//printf("%d\n",x);
for(int i = 0; i < w_G[x].size(); i++){
W_Edge & e = w_edges[w_G[x][i]];
if(!a[e.to] && e.cap > e.flow){
p[e.to] = w_G[x][i];
a[e.to] = min(a[x],e.cap - e.flow);
Q.push(e.to);
}
}
if(a[t]) break;
}
if(!a[t]) break;
for(int u = t; u != s; u = w_edges[p[u]].from){
w_edges[p[u]].flow += a[t];
w_edges[p[u] ^ 1].flow -= a[t];
}
flow += a[t];
}
return flow;
}
};
EdmondsKarp edm;
//----------------------------找在最短路径里的边--------------------------
void Find(){
edm.init();
int Size = edge.size();
for(int i = 0; i < Size; i++){
int d = dist[edge[i].u] - dist[edge[i].v];
if(d == edge[i].dist){
edm.add(edge[i].v,edge[i].u,1);
//printf("%d -> %d\n",edge[i].v,edge[i].u);
}
else if(- d == edge[i].dist){
edm.add(edge[i].u,edge[i].v,1);
//printf("%d -> %d\n",edge[i].u,edge[i].v);
}
}
}
//----------------------------main----------------------------------------
int main(){
while(scanf("%d%d",&n,&m) != EOF){
for(int i = 1; i <= n; i++) G[i].clear();
memset(vis,0,sizeof(vis));
edge.clear();
for(int i = 0; i < m; i++){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
G[x].push_back(Edge(y,z));
G[y].push_back(Edge(x,z));
edge.push_back(W(x,y,z));
}
bfs();
Find();
printf("%d %d\n",edm.Maxflow(1,n),m - min_num);
}
return 0;
}