spoj AMR11 Robbing Gringotts 双边暴力+hash+费用流

来源:互联网 发布:js同源策略是什么意思 编辑:程序博客网 时间:2024/06/07 00:55

   开始的时候,明显背包的复杂度是10000000*25*50 然后认为暴力的复杂度(1<<25)*50 还小于前者,然后就是各种剪纸,然后就是各种tle ,后面看题解又是暴力一半,hash一半,复杂度可以为(sqrt(1<<25)*50),可见解,然后就是一遍费用流,有km也可以吧,但是只会费用流,模板上,如果不懂暴力一半hash 一半的请看zoj3661,

#include<cstdio>#include<cstring>#define M 60#define N   200000#define mod 133331int n,m;int a[M][M];int map1[M][M];struct H{    int head[N],en;    struct E{        int u,v,next;    }e[N<<2];    void init(){        memset(head,-1,sizeof(head));en=0;    }    int change(int x){        return x%mod;    }    void add(int x){        int t1=change(x);        e[en].u=t1;e[en].v=x;e[en].next=head[t1];head[t1]=en++;    }    int find(int x){        int t1=change(x);        for(int i=head[t1];~i;i=e[i].next){            if(e[i].v==x) return 1;        }        return 0;    }}hash;int b[M];int ans[N],en;int tmax;void dfs1(int id,int level,int tsum){    if(level==a[id][0]/2+1){        ans[en++]=tsum;        return ;    }    dfs1(id,level+1,tsum+a[id][level]);    dfs1(id,level+1,tsum);}void dfs2(int id,int level,int tsum){    if(level==a[id][0]+1){        hash.add(tsum);        return ;    }    dfs2(id,level+1,tsum+a[id][level]);    dfs2(id,level+1,tsum);}void work1(){    for(int i=0;i<m;i++){        hash.init();        en=0;        dfs1(i,1,0);        dfs2(i,a[i][0]/2+1,0);        for(int j=0;j<n;j++){            int t1=b[j];            for(int k=0;k<en;k++){                int t2=ans[k];                if(t2>t1) continue;                int t3=t1-t2;                if(hash.find(t3)){                   map1[i][j]=1;                   break;                }            }        }    }}#define inf 0x3f3f3f3fusing namespace std;/*sumflow is max_flow*/const int MAXN=200;const int MAXM=10000;const int INF=inf;int sumflow;struct Edge{    int u,v,cap,cost,ednxt;}edge[MAXM<<2];int edn,head[MAXN],dist[MAXN],pp[MAXN];bool vis[MAXN];void init(){    edn=0,memset(head,-1,sizeof(head));}void addedge(int u,int v,int cap,int cost){    edge[edn].u=u,edge[edn].v=v,edge[edn].cap=cap,edge[edn].cost=cost, edge[edn].ednxt=head[u],head[u]=edn++;    edge[edn].u=v,edge[edn].v=u,edge[edn].cap=0,  edge[edn].cost=-cost,edge[edn].ednxt=head[v],head[v]=edn++;}int my_queue[MAXN<<3];int tp,hp;bool spfa(int s,int t,int n){    int i,u,v;    hp=0;tp=-1;    memset(vis,false,sizeof(vis));    memset(pp,-1,sizeof(pp));    for(i=0;i<=n;i++) dist[i]=INF;    vis[s]=true,dist[s]=0;    my_queue[++tp]=s;    while(tp>=hp)    {        u=my_queue[tp--];vis[u]=false;        for(i=head[u];i!=-1;i=edge[i].ednxt)        {            v=edge[i].v;            if(edge[i].cap&&dist[v]>dist[u]+edge[i].cost)            {                dist[v]=dist[u]+edge[i].cost;                pp[v]=i;                if(!vis[v])                {                    my_queue[++tp]=v;                    vis[v]=true;                }            }        }    }    if(dist[t]==INF)return false;    return true ;}int mcmf(int s,int t,int n){    int flow=0;    int i,minflow,mincost;    mincost=0;    while(spfa(s,t,n))    {        minflow=INF+1;        for(i=pp[t];i!=-1;i=pp[edge[i].u])            if(edge[i].cap<minflow)                minflow=edge[i].cap;        flow+=minflow;        for(i=pp[t];i!=-1;i=pp[edge[i].u])        {            edge[i].cap-=minflow;            edge[i^1].cap+=minflow;        }        mincost+=dist[t]*minflow;    }    sumflow=flow;    return mincost;}int build(int n,int m){    int sp=0;tp=n+m+1;    init();    for(int i=1;i<=n;i++){        addedge(sp,i,1,0);    }    for(int i=1;i<=m;i++){        addedge(i+n,tp,1,0);    }    for(int i=1;i<=n;i++){        for(int j=1;j<=m;j++){            if(map1[j-1][i-1]==1){                addedge(i,j+n,1,-b[i-1]);            }        }    }    int ans=mcmf(sp,tp,tp+2);    return -ans;}int main(){    int cas;while(~scanf("%d",&cas)){        while(cas--){            scanf("%d%d",&n,&m);            for(int i=0;i<n;i++) scanf("%d",&b[i]);            for(int i=0;i<m;i++){                scanf("%d",&a[i][0]);                for(int j=1;j<=a[i][0];j++){                    scanf("%d",&a[i][j]);                }            }            memset(map1,0,sizeof(map1));            work1();            int ans=build(n,m);//建图            printf("%d\n",ans);        }    }    return 0;}/*1004 43 7 8 103 1 2 42 3 74 0 0 0 01 1*/

时间好像排到到前几吧,ye

原创粉丝点击