SGU -1500 - Pass Licenses

先上題目:ide

1500. Pass Licenses

Time limit: 2.5 second
Memory limit: 64 MB
A New Russian Kolyan believes that to spend his time in traffic jams is below his dignity. This is why he had put an emergency flashlight upon the roof of his Hummer and had no problems until a recent decision of the city administration. Now each street of the city belongs to one or several categories, and a driver must have a separate license in order to use an emergency flashlight in the streets of each category. If a street belongs to several categories, it is sufficient to have a license only for one of these categories. For each category, a license is issued by a separate city official. Although these officials are different, they accept bribes of the same amount for giving a license. Help Kolyan to find a way from his home to work such that he can go this way with his flashlight turned on and having spent the minimal amount of money for bribes.

Input

The input contains the street plan in the following format. There are integers  KN, and  M in the first line, where  K is the number of street categories (1 ≤  K ≤ 20),  N is the number of crossroads (2 ≤  N ≤ 30), and  M is the number of descriptions of street segments between crossroads.
Each of the next  M lines describes a street segment by three integers  V1  V2  C, where  V1 and  V2 are the numbers of the crossroads limiting this segment, and  C is its category. Crossroads are numbered from 0 to  N – 1, categories are numbered from 0 to  K – 1. For any pair of crossroads no two segments of the same category connect these crossroads.

Output

Output in the first line the minimal number of licenses necessary for going from the crossroad 0 (Kolyan's home) to the crossroad 1 (Kolyan's work) with an emergency flashlight turned on.
In the second line, give the list of categories for which licenses must be obtained. The numbers should be separated with spaces. It is guaranteed that such list is always exist.

Sample

input output
3 3 3
0 2 0
0 2 1
1 2 2
2
0 2

 

 

  題意:給出n個點m條邊(無向),有k種駕照,每條邊若是想經過的話須要某一種駕照,問你從0號點到1號點最少須要多少種駕照,並把它們輸出。this

  作法:狀態壓縮而後暴力檢查是否合法,記錄最少須要多少中駕照。spa

  s[i][j]表示從i->j的話有哪幾種能夠用的駕照。而後枚舉不一樣的駕照組合,找到最少須要的數目之後輸出便可。ssr

 

上代碼:code

 

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <utility>
 4 #include <set>
 5 #define MAX 32
 6 #define MK(x,y) (make_pair(x,y))
 7 using namespace std;
 8 
 9 int s[MAX][MAX];
10 bool vis[MAX];
11 int k,n,m;
12 
13 bool dfs(int u,int caps) {
14     vis[u]=1;
15     if(u==1) return 1;
16     for(int i=0;i<n;i++){
17         if(!vis[i] && (caps&s[u][i])){
18             if(dfs(i,caps)) return 1;
19         }
20     }
21     return 0;
22 }
23 
24 int main() {
25     int u,v,cap,ans,caps,f;
26     //freopen("data.txt","r",stdin);
27     while(scanf("%d %d %d",&k,&n,&m)!=EOF) {
28         memset(s,0,sizeof(s));
29         for(int i=0;i<m;i++){
30             scanf("%d %d %d",&u,&v,&cap);
31             if(u==v) continue;
32             s[u][v]|=(1<<cap);
33             s[v][u]|=(1<<cap);
34         }
35         ans=k+1;
36         caps=0;
37         for(int i=1;i<(1<<k);i++){
38             int cnt=0;
39             for(int j=0;j<k;j++){
40                 if(i&(1<<j)) cnt++;
41             }
42             if(cnt>=ans) continue;
43             memset(vis,0,sizeof(vis));
44             if(dfs(0,i)){
45                 ans=cnt;
46                 caps=i;
47             }
48         }
49         printf("%d\n",ans);
50         f=0;
51         for(int i=0;caps>0;caps>>=1,i++){
52             if(caps&1){
53                 if(f++) printf(" ");
54                 printf("%d",i);
55             }
56         }
57         printf("\n");
58     }
59     return 0;
60 }
/*SGU 1500*/
相關文章
相關標籤/搜索