记录编号 |
93814 |
评测结果 |
AAAAAAAAAA |
题目名称 |
[SGU U206]道路 |
最终得分 |
100 |
用户昵称 |
cstdio |
是否通过 |
通过 |
代码语言 |
C++ |
运行时间 |
0.044 s |
提交时间 |
2014-03-28 16:44:19 |
内存使用 |
0.97 MiB |
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
const int SIZEN=410,SIZEn=110,INF=0x7fffffff/2;
int n,m;
class EDGE{
public:
int from,to,cost,id;
};
vector<EDGE> edges;
vector<int> c[SIZEN];
int father[SIZEn]={0};
bool flag[SIZEn]={0};
int depth[SIZEn]={0};
int N;//二分图左右两端的点数
int cedge[SIZEN][SIZEN]={0};
int slack[SIZEN]={0};
bool visitx[SIZEN]={0},visity[SIZEN]={0};//右边的访问
int labelx[SIZEN]={0},labely[SIZEN]={0};
int match[SIZEN]={0};//右连左
bool findpath(int cx[SIZEN][SIZEN],int u){//左右都是1~N,左到右的邻接矩阵是cx
visitx[u]=true;
for(int i=1;i<=N;i++){
if(visity[i]) continue;
int t=labelx[u]+labely[i]-cx[u][i];
if(t==0){//位于导出子图
visity[i]=true;
if(match[i]==-1||findpath(cx,match[i])){
match[i]=u;
return true;
}
}
else slack[i]=min(slack[i],t);
}
return false;
}
int KM(int cx[SIZEN][SIZEN]){
memset(match,-1,sizeof(match));
memset(labely,0,sizeof(labely));
for(int i=1;i<=N;i++){
labelx[i]=INF;
for(int j=1;j<=N;j++) labelx[i]=max(labelx[i],cx[i][j]);
}
for(int i=1;i<=N;i++){
while(true){
memset(visitx,0,sizeof(visitx)),memset(visity,0,sizeof(visity));
for(int j=1;j<=N;j++) slack[j]=INF;
if(findpath(cx,i)) break;
int d=INF;
for(int j=1;j<=N;j++) if(!visity[j]) d=min(d,slack[j]);
for(int j=1;j<=N;j++) if(visitx[j]) labelx[j]-=d;
for(int j=1;j<=N;j++) if(visity[j]) labely[j]+=d;
}
}
int ans=0;
for(int i=1;i<=N;i++) if(match[i]!=-1) ans+=cx[match[i]][i];
return ans;
}
void work(void){
int ans=KM(cedge);
printf("%d\n",ans);
//以下是输出方案的部分
/*for(int i=1;i<=n-1;i++) printf("%d\n",edges[2*i-2].cost-labelx[i]);
for(int i=n;i<=m;i++) printf("%d\n",edges[2*i-2].cost+labely[i]);*/
}
void addcedge(int v,int k){//x和其父亲边,第k条边
EDGE &F=edges[father[v]];
cedge[F.id][edges[k].id]=F.cost-edges[k].cost;
}
void makegraph(void){
for(int i=2*(n-1);i<edges.size();i+=2){//正着和倒着只需要来一次
int u=edges[i].from,v=edges[i].to;
if(depth[u]>depth[v]) swap(u,v);//u在上v在下
while(depth[v]>depth[u]) addcedge(v,i),v=edges[father[v]].from;
while(u!=v) addcedge(v,i),addcedge(u,i),v=edges[father[v]].from,u=edges[father[u]].from;
}
}
void DFS(int x,int f){
flag[x]=true;
father[x]=f;
for(int i=0;i<c[x].size();i++){
EDGE &now=edges[c[x][i]];
if(now.id<=n-1&&!flag[now.to]){
depth[now.to]=depth[x]+1;
DFS(now.to,c[x][i]);
}
}
}
void read(void){
scanf("%d%d",&n,&m);
int a,b,w;
for(int i=1;i<=m;i++){
scanf("%d%d%d",&a,&b,&w);
edges.push_back((EDGE){a,b,w,i});
edges.push_back((EDGE){b,a,w,i});
int tot=edges.size()-2;
c[a].push_back(tot);
c[b].push_back(tot+1);
}
N=m;
}
int main(){
freopen("sgu206roads.in","r",stdin);
freopen("sgu206roads.out","w",stdout);
read();
DFS(1,-1);
makegraph();
work();
return 0;
}