1. 程式人生 > >poj 3041 (水題)

poj 3041 (水題)

ont width div out 相互 表示 圖片 tput nes

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

Bessie wants to navigate her spaceship through a dangerous asteroid field in the shape of an N x N grid (1 <= N <= 500). The grid contains K asteroids (1 <= K <= 10,000), which are conveniently located at the lattice points of the grid.

Fortunately, Bessie has a powerful weapon that can vaporize all the asteroids in any given row or column of the grid with a single shot.This weapon is quite expensive, so she wishes to use it sparingly.Given the location of all the asteroids in the field, find the minimum number of shots Bessie needs to fire to eliminate all of the asteroids.

Input

* Line 1: Two integers N and K, separated by a single space.
* Lines 2..K+1: Each line contains two space-separated integers R and C (1 <= R, C <= N) denoting the row and column coordinates of an asteroid, respectively.

Output

* Line 1: The integer representing the minimum number of times Bessie must shoot.

Sample Input

3 4
1 1
1 3
2 2
3 2

Sample Output

2

Hint

INPUT DETAILS:
The following diagram represents the data, where "X" is an asteroid and "." is empty space:
X.X
.X.
.X.


OUTPUT DETAILS:
Bessie may fire across row 1 to destroy the asteroids at (1,1) and (1,3), and then she may fire down column 2 to destroy the asteroids at (2,2) and (3,2). 題意:

行與行之間相互獨立,一個行可以就炸掉很多列。(列的道理一樣),如果替換一些字。

點與點之間相互獨立,一個點就可以炸掉很多邊。

思路就是上圖技術分享圖片 代碼:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<set>
#include<algorithm>
#include<map>
#define maxn 2005
typedef long long ll;
#define inf 10000009
using namespace std;
int n,k;
int zzz,x,y;
bool can[maxn][maxn];//can[][]表示計算機i能夠處理的任務
struct edge{
   int to,cap,rev;    //邊的終點,容量,反向邊
};
vector<edge>mp[maxn];  // 鄰接圖
bool vis[maxn];
void add_edge(int from,int to,int cap)   //建圖
{
    mp[from].push_back((edge){to,cap,mp[to].size()});
     mp[to].push_back((edge){from,0,mp[from].size()-1});  //反向弧
}
int dfs(int v,int t,int f)   //找增廣路 v,t是最終點  用了f的流量
{
   if(v==t)return f;
   vis[v]=true;
   for(int i=0;i<mp[v].size();i++)
   {
       edge &e=mp[v][i];
       if(!vis[e.to]&&e.cap>0)
       {
           int d=dfs(e.to,t,min(f,e.cap));  //遍歷所有的路徑
           if(d>0)
           {
               e.cap-=d;                    //求增加的流量
               mp[e.to][e.rev].cap+=d;
               return d;
           }
       }
   }
   return 0;
}
int max_flow(int s,int t)
{
    int flow=0;
    for(;;)
    {
        memset(vis,0,sizeof(vis));   //初始化
        int f=dfs(s,t,inf);
        if(f==0)return flow;
        flow+=f;
    }
}
void solve()
{
    int s=n+n+1;
    int t=s+1;
    for(int i=0;i<n;i++)
    {
        add_edge(s,i,1);
    }
    for(int i=0;i<n;i++)
    {
        add_edge(n+i,t,1);
    }
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            if(can[i][j]==1)
            {
                //cout<<i<<" "<<j;
               add_edge(i,n+j,1);
            }
        }
    }
    cout<<max_flow(s,t)<<endl;
}
int main()
{
    while(cin>>n>>k)
    {
        memset(can,0,sizeof(can));
        for(int i=0;i<k;i++)
        {
            cin>>x>>y;
            x--;
            y--;
          can[x][y]=1;
        }
        solve();
    }
    return 0;
}

poj 3041 (水題)