ZOJ 3613
来源:互联网 发布:守望先锋数据查询不了 编辑:程序博客网 时间:2024/04/29 05:19
斯坦纳树
#include<cstdio>#include<cstring>#include<queue>#define N 210#define M 5100using namespace std;int a[N],b[N];int a1[N],b1[N];int st[N],dp[N][1000],ans[1000];bool vis[N][1000];struct Edge{ int v,w,next;}edge[M*2];int n,m,k,K,ans2;int head[N],cnt;queue<int>q;void addedge(int u,int v,int w){ edge[cnt].v=v; edge[cnt].w=w; edge[cnt].next=head[u]; head[u]=cnt++; edge[cnt].v=u; edge[cnt].w=w; edge[cnt].next=head[v]; head[v]=cnt++;}void init(){ memset(head,-1,sizeof(head)); memset(st,0,sizeof(st)); memset(dp,-1,sizeof(dp)); memset(vis,0,sizeof(vis)); memset(ans,-1,sizeof(ans)); cnt=0;}void SPFA(){ int i; while(!q.empty()){ int x=q.front()/10000,y=q.front()%10000; vis[x][y]=0; q.pop(); for(i=head[x];i!=-1;i=edge[i].next){ int v=edge[i].v; if(dp[v][st[v]|y]==-1 || dp[v][st[v]|y]>dp[x][y]+edge[i].w){ dp[v][st[v]|y]=dp[x][y]+edge[i].w; if(!vis[v][st[v]|y] && (st[v]|y)==y){ vis[v][st[v]|y]=1; q.push(v*10000+(st[v]|y)); //一定要加括号 } } } }}void Steiner_Tree(){ int i,j,p,x; for(p=0;p<K;p++){ for(i=1;i<=n;i++){ if(st[i] && (st[i]&p)==0)continue; for(x=(p-1)&p;x;x=(x-1)&p) if(dp[i][x|st[i]]!=-1 && dp[i][(p-x)|st[i]]!=-1) if(dp[i][p]==-1 || (dp[i][p]>dp[i][x|st[i]]+dp[i][(p-x)|st[i]])) dp[i][p]=dp[i][x|st[i]]+dp[i][(p-x)|st[i]]; if(dp[i][p]!=-1){ q.push(i*10000+p); vis[i][p]=1; } } SPFA(); }}bool check(int u){ int i,a2=0,b2=0; for(i=0;i<k;i++) if(u&(1<<i)){ a2+=a1[i]; b2+=b1[i]; } return b2<=a2;}int cout(int u){ int i,a2=0,b2=0; for(i=0;i<k;i++) if(u&(1<<i)){ a2+=a1[i]; b2+=b1[i]; } return min(a2,b2);}void solve(){ int i,j; int num=0,ans1=0; for(i=0;i<K;i++) for(j=1;j<=n;j++) if(dp[j][i]!=-1) if(ans[i]==-1 || ans[i]>dp[j][i]) ans[i]=dp[j][i]; for(i=0;i<K;i++){ //if(check(i)){ //这里只需去找那些工厂大于等于resource planets个数的状态即可 for(j=(i-1)&i;j;j=(j-1)&i) if((check(i) && check(j) && check(i-j)) || (!check(i) && !check(j) && !check(i-j))) //或者找划分中工厂个数与resource planets个数不等式同方向的 if(ans[j]!=-1 && ans[i-j]!=-1) if(ans[i]==-1 || ans[i]>ans[j]+ans[i-j]) ans[i]=ans[j]+ans[i-j]; int cou=cout(i); if(ans[i]!=-1) //一定要加这个判断 if(cou>num || (cou==num && ans[i]<ans1)) num=cou,ans1=ans[i]; //} } printf("%d %d\n",num/*+ans2*/,ans1);}int main(){ int i,u,v,w; while(scanf("%d",&n)==1){ k=ans2=0; init(); for(i=1;i<=n;i++){ scanf("%d %d",&a[i],&b[i]); /*if(a[i]&&b[i]){ a[i]--; b[i]--; ans2++; }*/ if(a[i]||b[i]){ a1[k]=a[i],b1[k]=b[i]; st[i]=1<<(k++); dp[i][st[i]]=0; } } K=1<<k; scanf("%d",&m); for(i=1;i<=m;i++){ scanf("%d %d %d",&u,&v,&w); addedge(u,v,w); } Steiner_Tree(); solve(); } return 0;}
- ZOJ 3613
- ZOJ 3613 Wormhole Transport
- ZOJ
- ZOJ
- ZOJ
- ZOJ
- ZOJ
- ZOJ
- ZOJ
- ZOJ
- ZOJ
- ZOJ
- ZOJ
- ZOJ
- ZOJ
- ZOJ
- ZOJ
- ZOJ
- SQL问题--从题库随机抽题
- mysql找回管理员密码
- 开发人员必须学会的8个Linux命令
- 用于CLR模式的mysql简单封装完成
- 分辨毒药和蒸馏水
- ZOJ 3613
- 业界最年轻的领军人物--久其总工程师欧阳曜
- SQL Server | 第一天学习总结
- 指针内存分配
- 强势进军网络浏览?传三星正研发移动浏览器
- Ubuntu Linux 安装 VirtualBox
- Java Future使用,顺便求算丑数问题
- web开发之软件开发读书笔记(一)
- 物联网百强企业之十大RFID企业