题目大意:
有
N
台电脑,
分析:
二分最小值
ans
,将
>ans
的边删除,跑二分图判断即可,注意边权可负。
AC code:
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ONLINE_JUDGE
using namespace std;
const int MAXN = 509;
const int INF = 0x3f3f3f3f;
int n;
int g[MAXN][MAXN];
int minv = INF, maxv = -INF;
int tg[MAXN][MAXN];
int vis[MAXN];
int link[MAXN];
int read()
{
char c;
int x = 0, f = 1;
while(((c=getchar()) < '0' || c > '9') && c != '-');
if(c == '-') f = -1;
else x = c-'0';
while((c=getchar()) >= '0' && c <= '9') x = x*10+c-'0';
return x*f;
}
int dfs(int x)
{
for(int i = 1; i <= n; ++i)
if(!vis[i] && tg[x][i] != INF)
{
vis[i] = 1;
if(!link[i] || dfs(link[i]))
{
link[i] = x;
return 1;
}
}
return 0;
}
bool check(int limit)
{
int ret = 0;
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= n; ++j)
if(g[i][j] <= limit) tg[i][j] = g[i][j];
else tg[i][j] = INF;
memset(link, 0, sizeof(link));
for(int i = 1; i <= n; ++i)
{
memset(vis, 0, sizeof(vis));
ret += dfs(i);
}
return ret == n;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("sgu218.in", "r", stdin);
freopen("sgu218.out", "w", stdout);
#endif
n = read();
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= n; ++j)
{
g[i][j] = read();
maxv = max(maxv, g[i][j]);
minv = min(minv, g[i][j]);
}
int l = minv, r = maxv;
while(l < r)
{
int mid = (l+r)>>1;
if(check(mid)) r = mid;
else l = mid+1;
}
printf("%d\n", l);
check(l);
for(int i = 1; i <= n; ++i)
printf("%d %d\n", link[i], i);
#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
return 0;
}