题目:
给一个图,起点1,终点n
必须走最短路才能从起点到终点。问至少删除几条边使得无法从起点到终点。
且删除最多几条边,还可以从起点到终点。
分析:做最短路,所有满足dist[u] = dist[v] + w(v,u)的边都是最短路的边,
对这样的边,重新建图。新图加入e(u,v),边权为1
t到s作最短路d,就是最少需要的边数能够到达边数,总边数-d就是最多能删除的边
对新图t,s作网络流,求最小割,就是最少需要删除的边数。
#include<iostream>
#include<cstring>
#include<vector>
#include<cstdio>
#include<vector>
#include<queue>
#include<set>
using namespace std;
#define maxn 3000
#define pl pair<int,int>
#define V first
#define D second
vector<pl>head[maxn];
struct comp{
bool operator()(pl a, pl b){
if(a.D == b.D) return a.V < b.V;
return a.D < b.D;
}
};
int dist[maxn];
void work(int S,int E){
set<pl,comp> haha;
memset(dist,0x3f,sizeof(dist));
dist[S] = 0;
pl a,b; a.V = S; a.D = 0;
haha.insert(a);
int v,d,w;
while(haha.size() > 0){
do{
a = *haha.begin();
haha.erase(haha.begin());
}while(dist[a.V] < a.D && haha.size() > 0);
for(int i = 0;i < head[a.V].size(); i++){
v = head[a.V][i].V;
d = head[a.V][i].D;
if(dist[v] > dist[a.V] + d){
dist[v] = dist[a.V] + d;
b.V = v;
b.D = dist[v];
haha.insert(b);
}
}
}
}
int cnt = 0;
int head1[3000];
struct Edge{
int u,next,v,d;
};
Edge edge[1000000];
void addedge(int u,int v,int d){
edge[cnt].u = u;
edge[cnt].v = v;
edge[cnt].d = d;
edge[cnt].next = head1[u];
head1[u] = cnt++;
edge[cnt].v = u;
edge[cnt].u = v;
edge[cnt].d = 0;
edge[cnt].next = head1[v];
head1[v] = cnt++;
}
int floor[3000];
int bfs(int s,int t){
queue<int> q;
q.push(s);
memset(floor,0,sizeof(floor));
floor[s] = 1;
while(!q.empty()){
int u = q.front();
q.pop();
for(int j = head1[u]; j != -1; j=edge[j].next){
int v = edge[j].v;
if(floor[v] == 0){
floor[v] = floor[u]+1;
q.push(v);
}
}
}
return floor[t]-floor[s];
}
bool BFS(int s,int e){//分层
queue<int>Q;
memset (floor, 0, sizeof(floor));
while(Q.size() > 0) Q.pop();
Q.push(s);
floor[s] = 1;
while(!Q.empty()){
int u = Q.front();
Q.pop();
for(int i=head1[u];i!=-1;i=edge[i].next){
int v = edge[i].v;
if(floor[v]==0&&edge[i].d > 0){
Q.push(v);
floor[v] = floor[u] + 1;
}
}
}
return floor[e] != 0;
}
int DFS(int u, int e,int in){//dinic
if(u == e) return in;
int res = in,flowout;
for(int i = head1[u];i != -1;i = edge[i].next) {
int v = edge[i].v;
if(floor[v] != floor[u] + 1 || edge[i].d == 0 )
continue;
flowout = DFS(v, e,min(res,edge[i].d));
edge[i].d -= flowout;
edge[i^1].d += flowout;
res -= flowout;
}
return in - res;
}
int network(int s,int e){ //s 源
int max_flow = 0,flow;
while(BFS(s,e)){
while(flow = DFS(s,e,100000000))
max_flow += flow;
}
return max_flow;
}
int main(){
int n,m;
while(scanf("%d%d",&n,&m)!=EOF){
int u,v,d;
for(int i = 1;i <= n;i++)
head[i].clear();
for(int i = 0;i < m; i++){
scanf("%d%d%d",&u,&v,&d);
pl a(v,d);
head[u].push_back(a);
pl b(u,d);
head[v].push_back(b);
}
work(1,n);
memset(head1,-1,sizeof(head1));
cnt = 0;
for(int i = 1;i < n; i++){
for(int j = 0;j < head[i].size(); j++){
int u = head[i][j].V;
int d = head[i][j].D;
if(dist[u] == dist[i]+d)
addedge(u,i,1);
}
}
int ans1 = bfs(n,1);
int ans2 = network(n,1);
cout<<ans2<<" "<<m-ans1<<endl;
}
return 0;
}