1. 程式人生 > >[bzoj3291] Alice與能源計劃 (二分圖匹配)

[bzoj3291] Alice與能源計劃 (二分圖匹配)

i++ 一個 如果 name 字典 tin 滿足 tchar 超過

傳送門

Description

在夢境中,Alice來到了火星。不知為何,轉眼間Alice被任命為火星能源部長,並立刻面臨著一個嚴峻的考驗。為
了方便,我們可以將火星抽象成平面,並建立平面直角坐標系。火星上一共有N個居民點。每個居民點認為是平面
上的一個點。第i個居民點的坐標為(Xi,Yi),對能源的需求量為Poweri。每個居民點消耗的能源由它附近的發電
站提供。由於技術原因,一個居民點消耗的所有能源必須來自同一座發電站。自人類移民火星之初,政府就有一個
規模宏大的發電站建設計劃。按照這個計劃,政府將在火星上建立M座發電站,這M座發電站將是火星居民的全部能
量來源。其中,第i座發電站的坐標為(xi,yi),產生能量的上限值為Limiti,建設費用為Pricei。同樣由於技術原

因,第i座發電站只能為與它的距離不超過Ri的居民點提供能源。然而,由於政府的財政狀況一直十分緊張,截至
目前,這M座發電站中只有少量建成並投入使用,多數的發電站尚未開始建設。Alice的任務是修改這個計劃,使得
它更符合實際情況。根據新的規定,一座發電站產生的所有能源必須提供給同一個居民點。Alice知道這個規定意
味著N個居民點消耗的能源將分別由N座不同的發電站提供,而且為第i個居民點提供能源的那座發電站的Limit值一
定不小於Poweri。Alice需要在原計劃的M座發電站中選擇恰好N座發電站,並完全放棄剩余的M-N座發電站,使得這
N座發電站能夠滿足N個居民點的需要。對於一個可行的方案,設方案中選擇的N座發電站構成集合S,而已經建成的
發電站構成集合T,那麽定義這個方案的代價為即,一個方案的代價等於被選擇的且尚未建成的發電站的建設費用
之和加上沒有被選擇的且已經建成的發電站的建設費用之和。在所有可行方案中,你必須幫助Alice找到代價最小
的方案,並將選擇的N座發電站按編號從小到大的順序輸出。如果代價最小的方案不唯一,則輸出其中字典序最小
的方案。
註意,輸入文件包含多組測試數據。

Input

第一行包含一個正整數T,表示有T組測試數據。接下來依次是T組測試數據。
每組測試數據的第一行包含兩個整數N、M。
接下來N行,每行3個整數:Xi、Yi、Poweri。
再接下來M行,每行6個整數:xi、yi、Limiti、Pricei、Ri、Finishedi。

若Finishedi=1,表示第i座發電站已經建成;否則Finishedi=0,表示第i座發電站尚未開始建設。
1≤N≤400,1≤M≤500,1≤T≤10,0≤xi,yi,Xi,Yi,Pricei≤10000,
1≤Ri,Poweri,Limiti≤10000。不同的居民點或發電站的坐標有可能重合。
關於方案的字典序的大小關系的說明:
設方案A選擇的N座發電站的編號從小到大依次為A1,A2,…,AN;
設方案B選擇的N座發電站的編號從小到大依次為B1,B2,…,BN。
我們稱方案A比方案B字典序更小,當且僅當存在正整數i,滿足1≤i≤N,
使得對任意1≤k≤i-1有Ak=Bk,且Ai<Bi。

Output

對於每組測試數據:
若存在可行方案則輸出兩行。第一行為一個整數,表示最小代價;
第二行是若幹個遞增的整數,表示字典序最小的最優方案選擇的發電站的編號。
若不存在可行方案,則僅輸出一行為一個整數-1。

Sample Input

4

1 1

4 4 1

8 7 1 2 5 1

2 3

0 0 3

2 0 2

1 1 5 1 3 0

1 0 5 1 1 1

3 0 5 1 3 0

2 3

0 0 3

2 0 2

1 1 2 0 3 0

1 0 1 0 1 1

3 0 3 0 2 0

2 3

0 0 3

2 0 2

1 1 4 2 2 0

1 0 2 9 1 1

3 0 5 4 2 1

Sample Output

0

1

1

1 2

-1

6

1 2

HINT

第1組測試數據:

只有一個居民點,其坐標為(4,4),能源需求量Power1=1;僅一座發電站,其坐標為(8,7),產生的能量上限Limit1

=1,建設費用Price1=2,服務範圍半徑R1=5,Finished1=1表示已經建成。

兩個點之間的距離等於5不超過R1,並且Power1≤Limit1。因此唯一的可行方案是花費0的代價保留1號發電站,使

它為1號居民點提供能源。

第2組測試數據:任意選擇兩個發電站都是一個可行方案。最小代價是1,對應的方案有兩種:選擇1號和2號發電站;選擇2號和3號發電站。而前者的字典序更小。

第3組測試數據:不存在可行方案。

第4組測試數據:代價最小的方案唯一:選擇1號和2號發電站,代價為6。

Solution

很顯然可以用費用流做雖然會T233
具體就是S向發電站連費用的邊,其他正常連邊,對於已經建好的可以先把花費計到答案裏,然後把這個花費取負
然後發現其實只需要貪心地找花費最少的邊然後跑最大匹配即可

Code

//By Menteur_Hxy
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define F(i,a,b) for(register int i=(a);i<=(b);i++)
#define E(i,u) for(register int i=head[u],v;i;i=nxt[i])
#define add(a,b) nxt[++cnt]=head[a],to[cnt]=b,head[a]=cnt
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin)),p1==p2?EOF:*p1++)
using namespace std;
 
char buf[1<<21],*p1,*p2;
int read() {
    int x=0,f=1; char c=getchar();
    while(!isdigit(c)) {if(c=='-')f=-f; c=getchar();}
    while(isdigit(c)) x=(x<<1)+(x<<3)+c-48,c=getchar();
    return x*f;
}
 
const int N=510;
int n,m,ans,num,cnt,now;
int nxt[N*N],to[N*N],head[N];
int cho[N],vis[N],fr[N];
struct per{int x,y,p;}P[N];
struct sta{
    int x,y,l,p,r,id;
    bool operator < (const sta oth)const {
        if(p==oth.p) return id<oth.id;
        return p<oth.p;
    }
}S[N];
bool jud(int a,int b) {
    if(S[a].l<P[b].p) return 0;
    if((S[a].x-P[b].x)*(S[a].x-P[b].x)+(S[a].y-P[b].y)*(S[a].y-P[b].y)>S[a].r*S[a].r) return 0;
    return 1;
}
 
bool dfs(int x) {
    E(i,x) if(vis[(v=to[i])]!=now) {
        vis[v]=now;
        if(!fr[v]||dfs(fr[v])) {fr[v]=x; return 1;}
    }
    return 0;
}
 
int main() {
    int cas=read();
    while(cas--) {
        n=read(),m=read(); ans=0;
        F(i,1,n) {
            int x=read(),y=read(),da=read();
            P[i]=(per){x,y,da};
        }
        F(i,1,m) {
            int x=read(),y=read(),l=read();
            int p=read(),r=read(),f=read();
            S[i]=(sta){x,y,l,p,r,i};
            if(f) ans+=p,S[i].p=-p;
        }
        sort(S+1,S+1+m);
        cnt=num=0; memset(head,0,sizeof(head));
        F(i,1,m) F(j,1,n) if(jud(i,j)) add(i,j);
        memset(vis,-1,sizeof(vis));
        memset(fr,0,sizeof(fr));
        for(now=1;now<=m&&num<=n;now++) if(dfs(now)) 
            ans+=S[now].p,cho[++num]=S[now].id;
        if(num<n) {puts("-1");continue;}
        printf("%d\n",ans);
        sort(cho+1,cho+1+num);
        F(i,1,n) printf("%d%c",cho[i],(i==n?'\n':' '));
    }
    return 0;
}

[bzoj3291] Alice與能源計劃 (二分圖匹配)