Description
没有得到激光武器的苏联十分生气,他们决定派遣一支特种部队强行 登陆美国并造成一定的袭击。 Reddington 得到的情报是他们将在佛罗里达
海岸登陆,他决定派遣他的手下去阻击他们。可惜的是, Reddington 由于 不听从总统的意见,手中的部队只剩下了 N
个人。人与人之间会有一定的 矛盾值,第 i 个人与第 j 个人的矛盾值为 Ti,j,并且有 Ti,i = 0, Ti,j = Tj,i。
Reddington 希望将这 N 个人分为两支小分队,记为 A, B,每个人要么属 于分队 A 要么属于分队 B。对于一支小分队
S,其内部的不安值
显然的,假如一支分队的不安值很高,那么作战能力就会很差。现在 给定你 N 以及一个 N ∗ N 的矩阵 T,你需要告诉
Reddington,最小的 D(A) + D(B) 是多少。
Input
输入包括多组数据。 对于每组数据: 第一行一个整数 N。 接下来 N −1 行,第 i 行读入 N −i 个数,第 i 行第 j 个数表示
Ti,i+j。 2 ≤ N ≤ 250, 0 ≤ Ti,j ≤ 109,数据组数不超过 2 组
Output
一行,最小的 D(A) + D(B) 是多少
Sample Input
5
4 5 0 2
1 3 7
2 0
4
Sample Output
4
HINT
//一种最优方案为: A = {1, 2, 4}, B = {3, 5},此时 D(A) = 4, D(B) =0
题解
我居然开场就看错题了…挂机了半个多小时
明明就是要求max嘛qwq…
先考虑朴素做法
强行让 D ( A ) > D ( B ) D(A)>D(B) D(A)>D(B)
枚举 A A A集合中的最大边 c c c,我们可以二分 B B B集合的最大边 d d d
那么 c j > c c_j>c cj>c的,显然两个点要在他们之间
c < = c j < d c<=c_j<d c<=cj<d的,显然两个点不能在 B B B集合
剩余的边可以扔掉不管了
那么上面可以 2 − s a t 2-sat 2−sat强行 n 4 l o g n^4log n4log判
遇到这种情况肯定要找一些最优化的性质
对于一个偶环的最小边,他是不可能成为 A A A集合的最大边的,我们将他连接的两个点缩起来之后就出现了奇环,显然其不满足第一条限制
对于图中出现了奇环的,我们做完当前边后就退出。因为剩余的边显然均小于已加入的边,图中已出现奇环,不合法。但需要注意的是当前边是合法的
故在环上的操作仅有 1 1 1次,复杂度降为 n 3 l o g n^3log n3log
另外听说此题还有随机化的巧妙做法?
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<ctime>
#include<map>
#include<bitset>
#include<set>
#define LL long long
#define mp(x,y) make_pair(x,y)
#define pll pair<long long,long long>
#define pii pair<int,int>
using namespace std;
inline int read()
{
int f=1,x=0;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int stack[20];
inline void write(int x)
{
if(x<0){putchar('-');x=-x;}
if(!x){putchar('0');return;}
int top=0;
while(x)stack[++top]=x%10,x/=10;
while(top)putchar(stack[top--]+'0');
}
inline void pr1(int x){write(x);putchar(' ');}
inline void pr2(int x){write(x);putchar('\n');}
const int MAXN=255;
struct edge{int x,y,c,next;}a[MAXN*MAXN*8],E[MAXN*MAXN*2];int len,last[2*MAXN];
bool cmp(edge n1,edge n2){return n1.c>n2.c;}
void ins(int x,int y){len++;a[len].x=x;a[len].y=y;a[len].next=last[x];last[x]=len;}
int sta[2*MAXN],belong[2*MAXN],low[2*MAXN],dfn[2*MAXN],id,cnt,tp;
bool vis[2*MAXN];
void tarjan(int x)
{
sta[++tp]=x;vis[x]=true;
low[x]=dfn[x]=++id;
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(!dfn[y])tarjan(y),low[x]=min(low[x],low[y]);
else if(vis[y])low[x]=min(low[x],dfn[y]);
}
if(low[x]==dfn[x])
{
cnt++;int i;
do
{
i=sta[tp--];
belong[i]=cnt;
vis[i]=false;
}while(i!=x);
}
}
int rt[MAXN];
int findrt(int x){return rt[x]==x?rt[x]:rt[x]=findrt(rt[x]);}
int n,col[MAXN],vi[MAXN],tim;
vector<int> vec[MAXN];
void flu(int x)
{
vi[x]=tim;
for(int k=0;k<vec[x].size();k++)
{
int y=vec[x][k];
if(vi[y]!=tim)col[y]=col[x]^1,flu(y);
}
}
int ans,ln;
bool check(int u1,int u2)
{
len=0;memset(last,0,sizeof(last));
//1~n 选0 n+1~2*n 选1
for(int i=1;i<=ln;i++)
{
if(E[i].c>u1)
{
ins(E[i].x,E[i].y+n);ins(E[i].x+n,E[i].y);
ins(E[i].y,E[i].x+n);ins(E[i].y+n,E[i].x);
}
else if(E[i].c>u2)
{
ins(E[i].x+n,E[i].y);
ins(E[i].y+n,E[i].x);
}
else break;
}
// puts("YES");
// pr2(len);
memset(low,0,sizeof(low));memset(dfn,0,sizeof(dfn));
id=cnt=tp=0;memset(vis,false,sizeof(vis));
for(int i=1;i<=2*n;i++)if(!dfn[i])tarjan(i);
for(int i=1;i<=n;i++)if(belong[i]==belong[i+n])return false;
return true;
}
int ct=0;
void work(int u)
{
// ct++;
int l=u,r=ln+1,sum;
while(l<=r)
{
int mid=(l+r)/2;
if(check(E[u].c,E[mid].c))sum=E[mid].c,l=mid+1;
else r=mid-1;
}
ans=min(ans,E[u].c+sum);
}
int main()
{
// freopen("1.in","r",stdin);
while(scanf("%d",&n)!=EOF)
{
ln=0;
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)E[++ln].c=read(),E[ln].x=i,E[ln].y=j;
sort(E+1,E+1+ln,cmp);
for(int i=1;i<=n;i++)rt[i]=i;
memset(vi,0,sizeof(vi));tim=0;
memset(col,-1,sizeof(col));
ans=(1<<31-1);E[ln+1].c=0;
for(int i=1;i<=ln;i++)
{
int x=E[i].x,y=E[i].y;
int p=findrt(x),q=findrt(y);
if(p!=q)
{
if(col[x]==-1)col[x]=0;
vec[x].push_back(y);vec[y].push_back(x);tim++;
flu(x);ct++;
rt[p]=q;
work(i);
}
else
{
if(col[x]==col[y]){work(i);break;}
vec[x].push_back(y);vec[y].push_back(x);
}
// pr2(ct);
}
ct=0;
pr2(ans);
for(int i=1;i<=n;i++)vec[i].clear();
}
return 0;
}