HDU 3311 Dig The Wells

Dig The Wells

Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1233    Accepted Submission(s): 553

Problem Description
You may all know the famous story “Three monks”. Recently they find some places around their temples can been used to dig some wells. It will help them save a lot of time. But to dig the well or build the road to transport the water will cost money. They do not want to cost too much money. Now they want you to find a cheapest plan.
 
Input
There are several test cases.
Each test case will starts with three numbers n , m, and p in one line, n stands for the number of monks and m stands for the number of places that can been used, p stands for the number of roads between these places. The places the monks stay is signed from 1 to n then the other m places are signed as n + 1 to n + m. (1 <= n <= 5, 0 <= m <= 1000, 0 <=p <= 5000)
Then n + m numbers followed which stands for the value of digging a well in the ith place.
Then p lines followed. Each line will contains three numbers a, b, and c. means build a road between a and b will cost c.
 
Output
For each case, output the minimum result you can get in one line.
 
Sample Input
3 1 3
1 2 3 4
1 4 2
2 4 2
3 4 4
4 1 4
5 5 5 5 1
1 5 1
2 5 1
3 5 1
4 5 1
 
Sample Output
6
5
 
题意:PS(一开始看不懂参照了别人的博客翻译)给定N个寺庙,和M个另外的地方。然后给定点权,表示在这个点挖水井需要的代价。再给定边权,为建造无向边ij的代价。然后求怎样弄最小的代价使得前N个点,就是寺庙都能从挖的井里得到水。
 
  1 #include <iostream>
  2 #include <vector>
  3 #include <queue>
  4 #define move(a) (1<<(a))//每一寺庙是否有连通井
  5 using namespace std;
  6 const int N = 1010;
  7 const int inf = 0x3fffffff;
  8 struct node{
  9     int v,c;
 10 };
 11 int n,m,dp[1<<7][N],dis[N][N];//因为最多就是5个寺庙
 12 std::vector<node> mapp[N];
 13 
 14 void spfa(){//求最短路spfa的模板
 15     int vis[N]={0},ts,k;
 16     queue<int> q;
 17     for(int s=0;s<=n+m;s++){
 18         for(int j=0;j<=n+m;j++){
 19             dis[s][j]=inf;
 20         }
 21         dis[s][s]=0;
 22         q.push(s);
 23         while(!q.empty()){
 24             ts=q.front();
 25             q.pop();
 26             vis[ts]=0;
 27             k=mapp[ts].size();
 28             for(int j=0;j<k;j++){
 29                 int v=mapp[ts][j].v;
 30                 if(dis[s][v]>dis[s][ts]+mapp[ts][j].c){
 31                     dis[s][v]=dis[s][ts]+mapp[ts][j].c;
 32                     if(!vis[v]){
 33                         q.push(v);
 34                     }
 35                     vis[v]=1;
 36                 }
 37             }
 38         }
 39     }
 40 }
 41 
 42 void countDP(){
 43     for(int sta =1;sta<move(n+1);sta++){//初始化所有数据
 44         for(int i=0;i<=n+m;i++){
 45             dp[sta][i]=inf;
 46         }
 47     }
 48     for(int i=0;i<=n;i++){//第i个寺庙连通井的价钱
 49         for(int j=0;j<=n+m;j++){
 50             dp[move(i)][j]=dis[i][j];
 51         }
 52     }
 53     for(int sta=1;sta<move(n+1);sta++){
 54         if(sta&(sta-1)){//如果两数按位做与运算,如果有相同的寺庙都有连接再进行后面的
 55             for(int i=0;i<=n+m;i++){
 56                 for(int s=sta;s>0;s=(s-1)&sta){
 57                     if(dp[sta][i]>dp[sta^s][i]+dp[s][i]){//构成sta这种情况需要的更新
 58                         dp[sta][i]=dp[sta^s][i]+dp[s][i];
 59                     }
 60                 }
 61             }
 62             for(int i=0;i<=n+m;i++){
 63                 for(int j=0;j<=n+m;j++){
 64                     if(dp[sta][i]>dp[sta][j]+dis[j][i]){
 65                         dp[sta][i]=dp[sta][j]+dis[j][i];//更新这种sta情况下的dp数组
 66                     }
 67                 }
 68             }
 69         }
 70     }
 71 }
 72 
 73 int main(){
 74     cin.sync_with_stdio(false);
 75     int t,a,b;
 76     node e;
 77     while(cin>>n>>m>>t){
 78         for(int i=0;i<=n+m;i++){
 79             mapp[i].clear();
 80         }
 81         for(int i=1;i<=n+m;i++){
 82             cin>>e.c;
 83             e.v=i;
 84             mapp[0].push_back(e);
 85             e.v=0;
 86             mapp[i].push_back(e);
 87         }
 88         while(t--){
 89             cin>>a>>b>>e.c;
 90             e.v=a;
 91             mapp[b].push_back(e);
 92             e.v=b;
 93             mapp[a].push_back(e);
 94         }
 95         spfa();
 96         countDP();
 97         cout<<dp[move(n+1)-1][0]<<endl;//n个1表示全部寺庙都连通了井
 98     }
 99     return 0;
100 }

 

2017-01-22 14:54:05

posted @ 2017-01-22 14:56  ガ落涙『不變』  阅读(148)  评论(0编辑  收藏  举报