DLX (重複覆蓋+費用不爲1的最小費用)fzu Problem 2165 v11

 Problem 2165 v11

重複覆蓋, 費用不爲1的最小費用, DLX + 暴力搜索 + 最優性優化。100行,100列,最多10000個點。爲什麼不會超時呢???是數據水嗎??求解釋

#include<cstdio>
#include <iostream>
using namespace std;

const int INF = 0x3f3f3f3f;
const int maxnode = 110 * 110;
const int maxr = 110;
const int maxc = 110;

int U[maxnode],D[maxnode],L[maxnode],R[maxnode],C[maxnode], row[maxnode];
int H[maxr],S[maxc];
bool v[maxc];
int sz,ans;

int cost[110];///行的費用,從1開始

///行編號從1開始,列編號爲1~c,結點0爲表頭結點
///注意給行和列的編號
///注意sz,ans.要自己初始化和賦值!!!
void init(int r,int c)///傳入行列數
{
    for(int i=0; i<=c; ++i)
    {
        S[i]=0;
        D[i]=U[i]=i;
        L[i+1]=i;
        R[i]=i+1;
    }
    R[sz = c]=0;
    while(r)H[r--]=-1;
}
//int geth()//??
//{
//    int ret=0;
//    for(int c=R[0]; c; c=R[c]) v[c]=1;
//    for(int c=R[0]; c; c=R[c]) if(v[c])
//    {
//        v[c]=0, ++ret;
//        for(int i=D[c]; i!=c; i=D[i])
//            for(int j=R[i]; j!=i; j=R[j])v[C[j]]=0;
//    }
//    return ret;
//}
void remove(int c)
{
    for(int i=D[c]; i!=c; i=D[i])
        R[L[i]]=R[i],L[R[i]]=L[i];
}
void resume(int c)
{
    for(int i=U[c]; i!=c; i=U[i])
        R[L[i]]=L[R[i]]=i;
}
void Dance(int d)///第一次調用傳入0
{
    if (d >= ans) return ;
//    if(d+geth()>=ans)return;
    if(!R[0])
    {
        ans=d;
        return;
    }

//    int c = R[0];
//    for (i = R[0]; i; i = R[i])
//        if (S[i] < R[c]) c = i;
    int c = R[0], tmp = maxnode;
    for (int i = R[R[0]]; i; i = R[i])
        if (S[i] < tmp) tmp = S[c = i];

    for(int i=D[c]; i!=c; i=D[i])
    {
        remove(i);
        for(int j=R[i]; j!=i; j=R[j])remove(j);
        Dance(d+cost[row[i]]);
        for(int j=L[i]; j!=i; j=L[j])resume(j);
        resume(i);
    }
}
void Link(int r,int c)
{
    ++S[C[++sz]=c];
    D[sz]=D[c];
    U[D[c]]=sz;
    U[sz]=c;
    D[c]=sz;
    row[sz] = r;
    if(H[r]<0)H[r]=L[sz]=R[sz]=sz;
    else
    {
        R[sz]=R[H[r]];
        L[R[H[r]]]=sz;
        L[sz]=H[r];
        R[H[r]]=sz;
    }
}

int n, m;
int main()
{
    while(cin >> n >> m)
    {
        init(m, n);
        for (int i = 1; i <= m; i++)
        {
            int xn;
            scanf("%d%d", &cost[i], &xn);
            for (int j = 0; j < xn; j++)
            {
                int x;
                scanf("%d",&x);
                Link(i, x);
            }
        }

        ans = INF;
        Dance(0);
        if (ans == INF) ans = -1;
        cout << ans << endl;
    }
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章