LightOJ

来源:互联网 发布:淘宝10元跳蛋靠谱吗 编辑:程序博客网 时间:2024/06/05 16:07

LightOJ - 1406入口

Altair is in great danger as he broke the three tenets of the assassin creed. The three tenets are: 1) never kill an innocent people, 2) always be discrete and 3) never compromise the brotherhood. As a result Altair is given another chance to prove that he is still a true assassin. Altair has to killn targets located inn different cities. Now as time is short, Altair can send a massage along with the map to the assassin's bureau to send some assassins who will start visiting cities and killing the targets. An assassin can start from any city, but he cannot visit a city which is already visited by any other assassin except him (because they do not like each other's work). He can visit a city multiple times though. Now Altair wants to find the minimum number of assassins needed to kill all the targets. That's why he is seeking your help.


Input

Input starts with an integer T (≤ 50), denoting the number of test cases.

Each case starts with a blank line. Next line contains two integers n (1 ≤ n ≤ 15) and m (0 ≤ m ≤ 50), where n denotes the number of cities and m denotes the number of one way roads. Each of the next m lines contains two integers u v (1 ≤ u, v ≤ n, u ≠ v) meaning that there is a road from u to v. Assume that there can be at most one road from a cityu to v.

Output

For each case, print the case number and the minimum number of assassins needed to kill all the targets.

Sample Input

2

 

3 2

1 2

2 3

 

6 6

1 2

2 3

2 4

5 4

4 6

4 2

Sample Output

Case 1: 1

Case 2: 2


题意:有n个(n<=15)城市,城市之间有m(m<=50)条单向路.刺客可以从任何一个城市出发去每个城市刺杀。每个刺客可以去自己去过的城市,但是不能去其他刺客去过的城市行刺,问最少需要几个刺客。

分析:状压DP,比赛时想到啦状压DP,可是子状态没有想清楚,导致wa。由于去过的城市还可以再去,走过的路还可以再走。那么在用dfs求子结构时用什么记录状态呢。

比赛时头脑有些混乱我当时记录的是每条路可以走100次(由于DFS的局限性,走完是不可能走完的),毕竟只有15个城市,但是还是wa。最后想到应该用已经访问过的点,和将访问的的点记录状态。然后就能找出能够一个刺客访问的所有城市集合。状态较多,用记忆化搜索节省时间。

#include<iostream>#include<cstdio>#include<cstring>#include<vector>using namespace std;const int INF=0x3f3f3f3f;bool v[1<<16][16],used[1<<16];int dp[1<<16],n,m,t;vector<int> g[16];void dfs(int x,int s){    used[s]=true;    for(int i=0;i<g[x].size();i++)    {        int y=g[x][i];        if(v[s][y])continue;        v[s][y]=true;        dfs(y,s|(1<<y));    }}int dis(int s){    int &res=dp[s];    if(res!=-1)return res;    res=200;    for(int i=s;i>0;i=(i-1)&s)    {        if(used[i])        {            res=min(res,1+dis(s^i));        }    }    return res;}int main(){    int T,x,y,cas=1;    scanf("%d",&T);    while(T--)    {        scanf("%d%d",&n,&m);        for(int i=0;i<=n;i++)            g[i].clear();        for(int i=1;i<=m;i++)        {            scanf("%d%d",&x,&y);            x--;y--;            g[x].push_back(y);        }        memset(v,false,sizeof(v));        memset(used,false,sizeof(used));        for(int i=0;i<n;i++)            dfs(i,1<<i);        memset(dp,-1,sizeof(dp));        dp[0]=0;        t=1<<n;        printf("Case %d: %d\n",cas++,dis(t-1));    }    return 0;}



原创粉丝点击