记录编号 94503 评测结果 AAAAAAAAAA
题目名称 [SPOJ 839] 最优标号 最终得分 100
用户昵称 Gravatarcstdio 是否通过 通过
代码语言 C++ 运行时间 0.273 s
提交时间 2014-04-01 16:07:56 内存使用 1.57 MiB
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;
typedef long long ll;
const int SIZEN=510,INF=0x7fffffff/2;
class EDGE{
public:
	int from,to,cap,flow;
};
vector<EDGE>  edges;
vector<int> c[SIZEN];
int id[SIZEN][SIZEN]={0};
bool connected[SIZEN][SIZEN]={0};
int depth[SIZEN]={0},cur[SIZEN]={0};
int N,S,T;//0~N
void addedge(int from,int to,int cap){
	edges.push_back((EDGE){from,to,cap,0});
	edges.push_back((EDGE){to,from,0,0});
	int tot=edges.size()-2;
	c[from].push_back(tot);
	c[to].push_back(tot+1);
	id[from][to]=tot;//,id[to][from]=tot+1;
}
bool BFS(void){
	bool visit[SIZEN]={0};
	queue<int> Q;
	Q.push(S);
	depth[S]=0;visit[S]=true;
	while(!Q.empty()){
		int x=Q.front();Q.pop();
		for(int i=0;i<c[x].size();i++){
			EDGE &now=edges[c[x][i]];
			if(!visit[now.to]&&now.cap>now.flow){
				visit[now.to]=true;
				depth[now.to]=depth[x]+1;
				Q.push(now.to);
			}
		}
	}
	return visit[T];
}
int DFS(int x,int a){//节点x,剩余流量a可分
	if(x==T||!a) return a;
	int flow=0,cf;//flow是当前已送出的流量
	for(int i=cur[x];i<c[x].size();i++){
		EDGE &now=edges[c[x][i]];
		if(depth[now.to]==depth[x]+1){
			cf=DFS(now.to,min(a,now.cap-now.flow));
			if(cf){
				flow+=cf;
				a-=cf;
				edges[c[x][i]].flow+=cf,edges[c[x][i]^1].flow-=cf;
				if(!a){
					cur[x]=i+1;
					break;
				}
			}
		}
	}
	if(!flow) depth[x]=-1;//没有成功把a里面的任何流量送走,那么以后也就送不走了
	return flow;
}
int Dinic(void){
	int flow=0;
	while(BFS()){
		memset(cur,0,sizeof(cur));
		flow+=DFS(S,INF);
	}
	return flow;
}
int n,m,K;
pair<int,int> pred[SIZEN];
void rebuild(int k){//考虑第k位,建立和S,T有关的边
	for(int i=0;i<edges.size();i++) edges[i].flow=0;
	for(int i=1;i<=n;i++){//和S,T有关的边清空
		edges[id[S][i]].cap=0;
		edges[id[i][T]].cap=0;
	}
	for(int i=1;i<=K;i++){
		int u=pred[i].first,w=pred[i].second;
		w=((w>>(k-1))&1);
		if(w) edges[id[S][u]].cap=INF;//按1的往S连,因为要最小化下标和......英语拙计
		else edges[id[u][T]].cap=INF;
	}
}
bool visit[SIZEN]={0};
int ans[SIZEN]={0};
void DFS(int x){
	if(visit[x]) return;
	visit[x]=true;
	for(int i=0;i<c[x].size();i++){
		EDGE &now=edges[c[x][i]];
		if(now.flow>=now.cap) continue;
		DFS(now.to);
	}
}
ll costsum=0;
void test(int k){
	rebuild(k);
	costsum+=Dinic()*(ll)(1<<(k-1));
	memset(visit,0,sizeof(visit));
	DFS(S);
	for(int i=1;i<=n;i++){
		if(visit[i]) ans[i]=ans[i]*2+1;
		else ans[i]=ans[i]*2;
	}
}
void work(void){
	costsum=0;
	for(int i=31;i>=1;i--) test(i);
	printf("%lld\n",costsum);
	//for(int i=1;i<=n;i++) printf("%d\n",ans[i]);
}
void read(void){
	edges.clear();
	memset(id,0,sizeof(id));
	memset(ans,0,sizeof(ans));
	memset(pred,0,sizeof(pred));
	memset(connected,0,sizeof(connected));
	scanf("%d%d",&n,&m);
	N=n+1;S=0;T=N;
	for(int i=0;i<=N;i++) c[i].clear();
	int a,b;
	for(int i=1;i<=m;i++){
		scanf("%d%d",&a,&b);//这是可以被在割集中划分的
		addedge(a,b,1);
		addedge(b,a,1);
		connected[a][b]=connected[b][a]=true;
	}
	scanf("%d",&K);
	for(int i=1;i<=K;i++) scanf("%d%d",&pred[i].first,&pred[i].second);
	for(int i=1;i<=n;i++) addedge(S,i,0),addedge(i,T,0);//先建上,以后改权值
}
int main(){
	freopen("optimalmarks.in","r",stdin);
	freopen("optimalmarks.out","w",stdout);
	read();
	work();
	//下面是多组数据的内容
	/*int T;
	scanf("%d",&T);
	while(T--){
		read();
		work();
	}*/
	return 0;
}