標籤:
1、有一個n*n的矩陣,在矩陣上有k個行星,用武器射擊一次可以消滅一行或者一列的行星,求消滅所有的行星的最少射擊次數。
2、最小點覆蓋數 = 最大匹配數
主要在於轉化:看圖:
3、
/*頂點編號從0開始的鄰接矩陣(匈牙利演算法)二分圖匹配(匈牙利演算法的DFS實現)(鄰接矩陣形式)初始化:g[][]兩邊頂點的劃分情況建立g[i][j]表示i->j的有向邊就可以了,是左邊向右邊的匹配g沒有邊相連則初始化為0uN是匹配左邊的頂點數,vN是匹配右邊的頂點數左邊是X集,右邊是Y集調用:res=hungary();輸出最大匹配數優點:適用於稠密圖,DFS找增廣路,實現簡潔易於理解時間複雜度:O(VE)*/#include<iostream>#include<stdio.h>#include<string.h>using namespace std;const int MAXN=512;int uN,vN;//u,v 的數目,使用前面必須賦值int g[MAXN][MAXN];//鄰接矩陣,記得初始化int linker[MAXN];//linker[v]=u,表示v(右邊Y集合中的點)串連到u(左邊X集合中的點)bool used[MAXN];bool dfs(int u){//判斷以X集合中的節點u為起點的增廣路徑是否存在 for(int v=0;v<vN;v++)//枚舉右邊Y集合中的點 if(g[u][v]&&!used[v]){//搜尋Y集合中所有與u相連的未訪問點v used[v]=true;//訪問節點v if(linker[v]==-1||dfs(linker[v])){//是否存在增廣路徑 //若v是未蓋點(linker[v]==-1表示沒有與v相連的點,即v是未蓋點),找到增廣路徑 //或者存在從與v相連的匹配點linker[v]出發的增廣路徑 linker[v]=u;//設定(u,v)為匹配邊,v串連到u return true;//返回找到增廣路徑 } } return false;}int hungary(){//返回最大匹配數(即最多的匹配邊的條數) int res=0;//最大匹配數 memset(linker,-1,sizeof(linker));//匹配邊集初始化為空白 for(int u=0;u<uN;u++){//找X集合中的點的增廣路 memset(used,false,sizeof(used));//設Y集合中的所有節點的未訪問標誌 if(dfs(u))res++;//找到增廣路,匹配數(即匹配邊的條數)+1 } return res;}int main(){ int i,ans; int N,K; int R,C; while(~scanf("%d%d",&N,&K)){ uN=N;//匹配左邊的頂點數 vN=N;//匹配右邊的頂點數 memset(g,0,sizeof(g));//二分圖的鄰接矩陣初始化 for(i=0;i<K;++i){ scanf("%d%d",&R,&C); g[--R][--C]=1;//頂點編號從0開始的 } ans=hungary(); printf("%d\n",ans); } return 0;}View Code
POJ - 3041 Asteroids(最小點覆蓋數)