您的位置:首页 > 其它

BZOJ 1266 - 最短路 + 最小割

2015-12-17 19:57 351 查看
裸题。。

第一问最短路,第二问最小割。。

先求一发最短路图,然后建图,容量均为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
, done
, cur
;
bool vis
;

#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
;
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
);

init();
printf("%d\n", Dinic());

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: