1. 程式人生 > >POJ - 3020 Antenna Placement(最小覆蓋路徑)

POJ - 3020 Antenna Placement(最小覆蓋路徑)

bool 內容 res col 兩個 -s != 感覺 就是

---恢復內容開始---

https://vjudge.net/problem/POJ-3020

題意

*--代表城市,o--代表空地

給城市安裝無線網,一個無線網最多可以覆蓋兩座城市,問覆蓋所有城市最少要用多少無線。

分析

第一眼看沒什麽感覺,但要是想到需要處理的點是城市,那這個問題就是一個最小路徑覆蓋問題了。因為最多覆蓋兩個城市,即相鄰城市才匹配。最小路徑覆蓋=總節點數-最大匹配數。建圖時是雙向的,所以最大匹配數/2。

#include<iostream>
#include<cstring>
#include<cstdio>
#include
<vector> #include<algorithm> const int MAXN= 500;//最大頂點數 const int MAXM = 11000;//最大邊數 const int INF=0x3f3f3f3f; using namespace std; bool g[MAXN][MAXN],used[MAXN]; int linker[MAXN],index[MAXN][MAXN]; int dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}}; int tot; char s[MAXN][MAXN]; bool dfs(int u){
for(int v=0;v<tot;v++){ if(!used[v]&&g[u][v]){ used[v]=true; if(linker[v]==-1||dfs(linker[v])){ linker[v]=u; return true; } } } return false; } int hungry(){ int res=0; memset(linker,
-1,sizeof(linker)); for(int i=0;i<tot;i++){ memset(used,false,sizeof(used)); if(dfs(i)) res++; } return res; } int main(){ int t; scanf("%d",&t); while(t--){ int n,m; memset(index,-1,sizeof(index)); memset(g,false,sizeof(g)); scanf("%d%d ",&n,&m); tot=0; for(int i=0;i<n;i++){ gets(s[i]); for(int j=0;j<m;j++){ if(s[i][j]==*){ index[i][j]=tot++; } } } for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ if(index[i][j]!=-1){ for(int k=0;k<4;k++){ int x=i+dir[k][0]; int y=j+dir[k][1]; if(x>=0&&x<n&&y>=0&&y<m&&index[x][y]!=-1){ g[index[i][j]][index[x][y]]=true; } } } } } int res=hungry(); printf("%d\n",tot-res/2); } return 0; }

POJ - 3020 Antenna Placement(最小覆蓋路徑)