BZOJ 1266 - 最短路 + 最小割
裸题。。
第一问最短路,第二问最小割。。
先求一发最短路图,然后建图,容量均为1,然后Dinic最大流即可。。
// BZOJ 1266 #include <cstdio> #include <cstring> #include <queue> #include <algorithm> using namespace std; typedef long long LL; const int N=500+5, M=125000*2, INF=0x3f3f3f3f; // 注意边数要乘2! int n, m, u, v, t, c, d[N], done[N], cur[N]; bool vis[N]; #define rep(i,a,b) for (int i=a; i<=b; i++) #define dep(i,a,b) for (int i=a; i>=b; i--) #define read(x) scanf("%d", &x) #define fill(a,x) memset(a, x, sizeof(a)) struct Graph { // 因为有两张图,所以定义了一个基于邻接表的图的结构体 int s, from[M], to[M], dis[M], cap[M], pre[M], last[N]; void init() { s=-1; fill(last, -1); } // 注意要置为-1,因为边的标号从0开始 void ine(int a, int b, int c, int d) { s++; from[s]=a, to[s]=b, cap[s]=c, dis[s]=d, pre[s]=last[a]; last[a]=s; } void ine2(int a, int b, int c1, int c2, int d) { ine(a, b, c1, d); ine(b, a, c2, d); } } g1, g2; // 分别为原图和最短路图 #define reg(i,s,u) for (int i=s.last[u]; i!=-1; i=s.pre[i]) struct Node { int id, dis; Node(int id_, int dis_) { id=id_, dis=dis_; } bool operator < (const Node &x) const { return dis>x.dis; } // 注意优先队列是大根堆,所以定义小于号时要反着定义 }; int Q[2*N]; bool BFS(int s, int t) { rep(i,1,n) vis[i]=false; int head=1, tail=1; Q[1]=s; d[s]=0; vis[s]=true; while (head<=tail) { int x=Q[head++]; reg(i,g2,x) { int y=g2.to[i]; if (!vis[y] && g2.cap[i]>0) { vis[y]=true; d[y]=d[x]+1; Q[++tail]=y; } } } return vis[t]; } int DFS(int x, int a) { if (x==n || a==0) return a; int w, used=0; for (int &i=cur[x]; i!=-1; i=g2.pre[i]) { int y=g2.to[i]; if (d[y]==d[x]+1 && (w=DFS(y, min(a, g2.cap[i])))>0) { g2.cap[i]-=w; g2.cap[i^1]+=w; used+=w; a-=w; if (a==0) break; } } return used; } int Dinic() { int ret=0; rep(i,1,n) d[i]=INF; while (BFS(1,n)) { rep(i,1,n) cur[i]=g2.last[i]; ret+=DFS(1, INF); } return ret; } priority_queue<Node> pQ; void Dijkstra(int s) { rep(i,1,n) d[i]=INF, done[i]=false; d[s]=0; pQ.push(Node(s,0)); while (!pQ.empty()) { Node Nx=pQ.top(); pQ.pop(); int x=Nx.id; if (done[x]) continue; done[x]=true; reg(i,g1,x) { int y=g1.to[i], w=g1.dis[i]; if (done[y]) continue; if (d[x]+w<d[y]) { d[y]=d[x]+w; pQ.push(Node(y, d[y])); } } } } void init() { // 构建最短路图:加入d[to]=d[from]+1的边 g2.init(); rep(i,0,g1.s) { int u=g1.from[i], v=g1.to[i]; if (d[u]+g1.dis[i]==d[v]) g2.ine2(u, v, g1.cap[i], 0, 0); } } int main() { read(n); read(m); g1.init(); rep(i,1,m) read(u), read(v), read(t), read(c), g1.ine2(u, v, c, c, t); Dijkstra(1); printf("%d\n", d[n]); init(); printf("%d\n", Dinic()); return 0; }