hdu 4862解题报告

来源:互联网 发布:java web 开发 编辑:程序博客网 时间:2024/05/21 22:33

看完题写了个暴搜,果断T了..dp的话复杂度太高了,只能用网络流求解


仔细分析是一个费用流的模型,把费用取负就可以用最小费用流来跑了

费用流中的每条流就对应每次无限制的jump,按规则连好边

关键问题就是如何让所有点都被访问一次:拆点后设流量为1,费用为-10*10*10(不可能达到的能量)

还有就是设两个超级原点S和S',让S和S'直接的流量为K,费用为0,再让S'连向所有结点的入点(保证最多有K条流)


最后是费用流算法...开始上的zkw,跑不出正解...换了个spfa暴力费用流居然直接过了(好像zkw不能处理负cost的?)


#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <queue>using namespace std;const int maxm=20000;const int maxn=10*10*10;const int inf=0x3f3f3f3f;const int ddd=10*10*10;const int S=0,T=1;int N,M,K;int NN;char arr[11][11];struct EDGE{    int to,next,cap,cost,from;};EDGE edge[maxm];int box[maxn];int ent;void _add(int f,int t,int cap,int cost){    edge[ent].cap=cap;    edge[ent].cost=cost;    edge[ent].to=t;    edge[ent].from=f;    edge[ent].next=box[f];    box[f]=ent++;}void add(int f,int t,int cap,int cost){    _add(f,t,cap,cost);    _add(t,f,0,-cost);}int getp(int x,int y){    return (x*M+y)*2+2;}int in[maxn];int dis[maxn];int from[maxn];queue<int> que;bool spfa(int f,int t){    int now;    for(int i=0; i<NN; i++)        dis[i]=inf;    memset(in,0,sizeof(in));    memset(from,-1,sizeof(from));    que.push(f);    in[f]=1;    dis[f]=0;    while(!que.empty())    {        now=que.front();        que.pop();        for(int i=box[now]; i!=-1; i=edge[i].next)        {            if(edge[i].cap&&dis[edge[i].to]>dis[now]+edge[i].cost)            {                dis[edge[i].to]=dis[now]+edge[i].cost;                from[edge[i].to]=i;                if(!in[edge[i].to])                {                    que.push(edge[i].to);                    in[edge[i].to]=1;                }            }        }        in[now]=0;    }    if(dis[t]==inf) return 0;    return dis[t];}int fyl(int f,int t){    int cost=0;    int mincap;    while(spfa(f,t))    {        mincap=inf;        for(int i=from[t]; i!=-1; i=from[edge[i].from])            mincap=min(mincap,edge[i].cap);        for(int i=from[t]; i!=-1; i=from[edge[i].from])        {            edge[i].cap-=mincap;            edge[i^1].cap+=mincap;        }        cost+=dis[t]*mincap;    }    return cost;}void buildMap(){    ent=0;    memset(box,-1,sizeof(box));    NN=N*M*2+5;    int SS=N*M*2+4;    add(S,SS,K,0);    for(int i=0; i<N; i++)        for(int j=0; j<M; j++)        {            add(getp(i,j),getp(i,j)+1,1,-ddd);            add(SS,getp(i,j),1,0);            add(getp(i,j)+1,T,1,0);            for(int k=i+1; k<N; k++)            {                add(getp(i,j)+1,getp(k,j),1,(k-i-1)-(arr[i][j]==arr[k][j]?arr[i][j]-'0':0));            }            for(int k=j+1; k<M; k++)            {                add(getp(i,j)+1,getp(i,k),1,(k-j-1)-(arr[i][j]==arr[i][k]?arr[i][j]-'0':0));            }        }}int main(){    freopen("in.txt","r",stdin);    int T;    scanf("%d",&T);    for(int cas=1; cas<=T; cas++)    {        printf("Case %d : ",cas);        scanf("%d%d%d",&N,&M,&K);        for(int i=0; i<N; i++)            for(int j=0; j<M; j++)                cin>>arr[i][j];        if(K<min(N,M))        {            printf("-1\n");            continue;        }        buildMap();        printf("%d\n",-fyl(0,1)-N*M*ddd);    }    return 0;}


0 0
原创粉丝点击