P4610 [COCI2011-2012#7] KAMPANJA

题目背景

临近选举,总统要在城市1和城市2举行演讲。他乘汽车完成巡回演讲,从1出发,途中要经过城市2,最后必须回到城市1.特勤局对总统要经过的所有城市监控。为了使得费用最小,必须使得监控的城市最少。求最少要监控的城市。

题目描述

一共有N个城市,有M条有向边。(0<=N,M<=200)有N从1出发途中要经过2,最后要回到1的路线中最少要经过的点的数目。

输入输出格式

输入格式:

第一行包含222个整数N,MN表示城市的数目,M表示有向边的数目。 接下来M行,每行两个数A,B,表示从AB有一条有向边。

输出格式:

最少要监控的城市的数量。

输入输出样例

输入样例#1: 
6 7
1 3
3 4
4 5
5 1
4 2
2 6
6 3
输出样例#1: 
6

说明

0<=N,M<=200

本题数据加强by Imagine

Solution:

  本题最短路+dp。

  我们先用floyd预处理出$w[i][j]$,表示$i\rightarrow j$经过的最少点数(除了i)。

  由于要求$1\rightarrow 2\rightarrow 1$经过的最少点数,而模型是个DAG,考虑dp,定义状态$f[i][j]$表示$i\rightarrow 2\rightarrow j$的经过的最少点数,初始化$f[2][2]=1$,状态转移方程:$f[x][y]=min(f[x][y],f[a][b]+w[b][x]+w[x][y]+w[y][a]-1)$(注意-1是因为a被多算了1次),那么转移时贪心的用没访问过的全局最小值$f[a][b]$去转移就好了。

代码:

/*Code by 520 -- 9.4*/
#include<bits/stdc++.h>
#define il inline
#define ll long long
#define RE register
#define For(i,a,b) for(RE int (i)=(a);(i)<=(b);(i)++)
#define Bor(i,a,b) for(RE int (i)=(b);(i)>=(a);(i)--)
using namespace std;
const int N=205,inf=233333333;
int n,m,w[N][N],dis[N][N];
bool vis[N][N];

int main(){
    scanf("%d%d",&n,&m);
    For(i,1,n) For(j,1,n) w[i][j]=i==j?0:inf,dis[i][j]=inf;
    int u,v;
    while(m--) scanf("%d%d",&u,&v),w[u][v]=1;
    For(k,1,n) For(i,1,n) For(j,1,n) w[i][j]=min(w[i][j],w[i][k]+w[k][j]);
    dis[2][2]=1;
    while(1){
        int a=-1,b=-1;
        For(i,1,n) For(j,1,n) 
            if(vis[i][j]) continue;
            else if(a==-1||dis[i][j]<dis[a][b]) a=i,b=j;
        if(a==1&&b==1)break;
        vis[a][b]=1;
        For(c,1,n) For(d,1,n) {
            if(c==a||c==b||d==a||d==b)continue;
            dis[c][d]=min(dis[c][d],dis[a][b]+w[b][c]+w[c][d]+w[d][a]-1);
        }
    }
    cout<<dis[1][1];    
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/five20/p/9589063.html