上海高校金马五校赛 J - 小Y写文章

题目大意: 给你n个数字, 定义不连贯值为, max(abs(a[ i ] - b[ i ])) ,现在让你把m个新的数字插入n + 1 个空位中,使得不连贯值最小。

 

思路:二分不连贯值, 每次进行二分图匹配, 注意进行二分图匹配的时候需要加入虚拟的点,因为这n + 1个空位中有些点是必须加数字的。

  1 #include<bits/stdc++.h>
  2 #define LL long long
  3 #define fi first
  4 #define se second
  5 #define mk make_pair
  6 #define pii pair<int, int>
  7 using namespace std;
  8 
  9 const int N=400+7;
 10 const int M=100+7;
 11 const int inf=0x3f3f3f3f;
 12 const LL INF=0x3f3f3f3f3f3f3f3f;
 13 const int mod=1e9 + 9;
 14 
 15 int n, m, a[N], b[N],cx[N], cy[N], vis[N];
 16 vector<int> edge[N];
 17 
 18 bool path(int u)
 19 {
 20     for(int v : edge[u])
 21     {
 22         if(!vis[v])
 23         {
 24             vis[v] = 1;
 25             if(cy[v] == -1 || path(cy[v]))
 26             {
 27                 cx[u] = v;
 28                 cy[v] = u;
 29                 return true;
 30             }
 31         }
 32     }
 33     return false;
 34 }
 35 
 36 bool maxmatch()
 37 {
 38     int res=0;
 39     memset(cx, -1, sizeof(cx));
 40     memset(cy, -1, sizeof(cy));
 41     for(int i = 1; i <= 2 * n + 2; i++)
 42     {
 43         if(cx[i] == -1)
 44         {
 45             memset(vis, 0, sizeof(vis));
 46             if(path(i)) continue;
 47             else return false;
 48         }
 49     }
 50     return true;
 51  }
 52 
 53 bool check(int x) {
 54     for(int i = 1; i <= 2 * n + 2; i++)
 55         edge[i].clear();
 56     for(int i = 1; i <= n + 1; i++) {
 57         if(i == 1) {
 58             for(int j = 1; j <= m; j++) {
 59                 if(abs(b[j] - a[1]) <= x) {
 60                     edge[i].push_back(n + 1 + j);
 61                     edge[n + 1 + j].push_back(i);
 62                 }
 63             }
 64             for(int j = m + 1; j <= n + 1; j++) {
 65                 edge[i].push_back(n + 1 + j);
 66                 edge[n + 1 + j].push_back(i);
 67             }
 68         } else if(i == n + 1) {
 69             for(int j = 1; j <= m; j++) {
 70                 if(abs(b[j] - a[n]) <= x) {
 71                     edge[i].push_back(n + 1 + j);
 72                     edge[n + 1 + j].push_back(i);
 73                 }
 74             }
 75             for(int j = m + 1; j <= n + 1; j++) {
 76                 edge[i].push_back(n + 1 + j);
 77                 edge[n + 1 + j].push_back(i);
 78             }
 79         } else {
 80             for(int j = 1; j <= m; j++) {
 81                 if((abs(b[j] - a[i]) <= x) && abs(b[j] - a[i - 1]) <= x) {
 82                     edge[i].push_back(n + 1 + j);
 83                     edge[n + 1 + j].push_back(i);
 84                 }
 85             }
 86             if(abs(a[i] - a[i - 1]) <= x) {
 87                 for(int j = m + 1; j <= n + 1; j++) {
 88                     edge[i].push_back(n + 1 + j);
 89                     edge[n + 1 + j].push_back(i);
 90                 }
 91             }
 92         }
 93     }
 94     return maxmatch();
 95 }
 96 int main() {
 97     int T; scanf("%d", &T);
 98     while(T--) {
 99         scanf("%d%d", &n, &m);
100         for(int i = 1; i <= n; i++)
101             scanf("%d", &a[i]);
102         for(int i = 1; i <= m; i++)
103             scanf("%d", &b[i]);
104 
105         int l = 0, r = 1e9, ans = -1;
106 
107         while(l <= r) {
108             int mid = (l + r) >> 1;
109             if(check(mid)) {
110                 ans = mid;
111                 r = mid - 1;
112             } else {
113                 l = mid + 1;
114             }
115         }
116         printf("%d\n", ans);
117     }
118     return 0;
119 }
120 /***************
121 ****************/

 

posted @ 2018-04-26 15:14  NotNight  阅读(181)  评论(0编辑  收藏  举报