Description
Input
Output
题目大意:要买n种东东,每种东东有一个价格。可以用4种方式买这些东东:1、直接用金币全额购买(没用的条件……);2、若东东k元,付k-1个金币加一个珠子买。;3、用一个东东加一些钱交换另一个东东。4:等价值的东东可以交换。问每个东东最少用多少钱可以卖到,有几个东东满足其实付等于另外两个东东的实付之和。
思路:图论水题。附加源点S,从S到每一个东东连边,代价为k-1(用珠子不用是浪费噢);N1能外加x元换到N2,就从N1连边到N2,代价为x;价格相同的东东之间连双向边,代价为0。每个东东到源点的最短路径就是最少用的钱,就是实际代价。最后要算的m,这么小的范围,果断暴力O(n³)枚举啦管他呢。
PS:无聊测试了一下输入前面的序号确实是按顺序给的(其实不给也没什么关系吧……)
代码(0MS):
1 #include <cstdio> 2 #include <algorithm> 3 #include <iostream> 4 #include <cstring> 5 using namespace std; 6 7 const int MAXN = 25; 8 const int MAXE = 2 * MAXN * MAXN; 9 const int INF = 0x3fff3fff; 10 11 struct Node { 12 int id, val; 13 void read() { 14 scanf("%d%d", &id, &val); 15 } 16 bool operator < (const Node &rhs) const { 17 return id < rhs.id; 18 } 19 }; 20 21 Node a[MAXN]; 22 int dis[MAXN], head[MAXN], vis[MAXN]; 23 int next[MAXE], to[MAXE], cost[MAXE]; 24 int ecnt, n, m; 25 26 void init() { 27 memset(head, 0, sizeof(head)); 28 ecnt = 1; 29 } 30 31 void add_edge(int u, int v, int c) { 32 to[ecnt] = v; cost[ecnt] = c; next[ecnt] = head[u]; head[u] = ecnt++; 33 } 34 35 void Dijkstra(int st, int n) { 36 memset(dis, 0x3f, sizeof(dis)); 37 memset(vis, 0, sizeof(vis)); 38 dis[st] = 0; 39 for(int x = 1; x < n; ++x) { 40 int u, minDis = INF; 41 for(int i = 0; i < n; ++i) 42 if(!vis[i] && dis[i] < minDis) u = i, minDis = dis[i]; 43 vis[u] = true; 44 for(int p = head[u]; p; p = next[p]) { 45 int v = to[p]; 46 if(!vis[v] && dis[v] > dis[u] + cost[p]) dis[v] = dis[u] + cost[p]; 47 } 48 } 49 } 50 51 void solve() { 52 init(); 53 scanf("%d", &m); 54 while(m--) { 55 int u, v, c; 56 scanf("%d%d%d", &u, &v, &c); 57 add_edge(u, v, c); 58 } 59 int st = 0; 60 for(int i = 1; i <= n; ++i) add_edge(st, i, a[i].val - 1); 61 for(int i = 1; i <= n; ++i) { 62 for(int j = 1; j <= n; ++j) { 63 if(i == j || a[i].val != a[j].val) continue; 64 add_edge(i, j, 0); 65 add_edge(j, i, 0); 66 } 67 } 68 Dijkstra(st, n + 1); 69 } 70 71 int main() { 72 int T; 73 scanf("%d", &T); 74 while(T--) { 75 scanf("%d", &n); 76 for(int i = 1; i <= n; ++i) a[i].read(); 77 sort(a + 1, a + n + 1); 78 solve(); 79 for(int i = 1; i <= n; ++i) printf("%d %d\n", i, dis[i]); 80 int ans = 0; 81 memset(vis, 0, sizeof(vis)); 82 for(int i = 1; i <= n; ++i) { 83 for(int j = 1; j <= n; ++j) { 84 if(i == j) continue; 85 for(int k = 1; k <= n; ++k) { 86 if(k == i || k == j) continue; 87 if(vis[k] || dis[i] + dis[j] != dis[k]) continue; 88 vis[k] = true; 89 ++ans; 90 } 91 } 92 } 93 printf("%d\n", ans); 94 } 95 }