定义:对于一个非负整数组成的序列,如果存在一个无向图的度序列和其一致,则该序列是可图的。
Havel-Hakimi定理:给定一个非负整数序列{d1,d2,...dn},若存在一个无向图使得图中各点的度与此序列一一对应,则称此序列可图化。
由非负整数组成的有限非递增序列,S={d1,d2,d3...dn},当且仅当S1={d2-1,d3-1...d(d1+1)-1,d(d1+2),d(d1+3),......dn}也是可图的
三题的解释都写注释里面了,懒得分开写,感觉写注释里清楚一点。
poj1659
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
const int N=15;
typedef struct hu{
int id;
int nu;
}hu;
hu num[N];
int t;
bool guan[N][N];
bool cmp(hu a,hu b){
return a.nu>b.nu;
}
bool f(int k)//k cur
{
sort(num+k,num+t+1,cmp);
if(num[t].nu<0)return 0;
if(k==t)return 1;
for(int i=k+1;i<=k+num[k].nu;i++)
{
num[i].nu--;
guan[num[i].id][num[k].id]=guan[num[k].id][num[i].id]=1;
}
f(k+1);
}
int main()
{
int n;
cin>>n;
while(n--)
{
cin>>t;
for(int i=1;i<=t;i++)
{
cin>>num[i].nu;
num[i].id=i;
}
memset(guan,0,sizeof(guan));
if(f(1))
{
cout<<"YES"<<endl;
for(int i=1;i<=t;i++)
{
for(int j=1;j<=t;j++)
{
cout<<guan[i][j]<<' ';
}
cout<<endl;
}
cout<<endl;
}
else cout<<"NO"<<endl<<endl;
}
}
poj2018
#include<iostream>
#define max(x,y) (x>y)?(x):(y)
#define min(x,y) (x<y)?(x):(y)
using namespace std;
const int N=100005;
double a[N];
double sum[N];
double d[N];
double sumd[N];
int main()
{
int n,f;
cin>>n>>f;
double maxx=0,minn=1e8;
sum[0]=0;
for(int i=1;i<=n;i++)
{
cin>>a[i];
maxx=max(maxx,a[i]);//取区间最大值
minn=min(minn,a[i]);//取区间最小值
}
int count=0;
while(maxx-minn>1e-4)//二分,精度题目中限定了三位小数
{
double mid=(maxx+minn)/2;
double maxxx=-1e8;
double minnn=1e8;
for(int i=1;i<=n;i++)
{
d[i]=a[i]-mid;//每个数减去当前的均值,很好的一个技巧,把对均值的增加减少的贡献,化为正负好判断
sumd[i]=sumd[i-1]+d[i];//前缀和
}
for(int i=f;i<=n;i++)//dp
{
minnn=min(minnn,sumd[i-f]);
maxxx=max(maxxx,sumd[i]-minnn);
}
if(maxxx>=0)minn=mid;
else maxx=mid;
}
cout<<int(maxx*1000)<<endl;
}
codeforces1073c
#include<iostream>
#include<string.h>
#include<string>
using namespace std;
#define abs(x) ((x>=0)?(x):(-x))
const int N=200005;
const int INF=0x3f3f3f3f;
int x[N];
int y[N];
int endx,endy;
int n;
bool check(int m)
{
for(int i=1;i+m-1<=n;i++){
int xx=x[n]-x[i+m-1]+x[i-1];
int yy=y[n]-y[i+m-1]+y[i-1];
//从i到i+m-1删去,即整个序列[1,i-1]+[m,n]的和
//tx ty是要修改的区间修改后应该对应的x和y
int tx=endx-xx;
int ty=endy-yy;
//二者的差值
//区间长m>=|tx|+|ty|而且m与|tx|+|ty|同奇偶,剩下的两两相消
if(abs(tx)+abs(ty)<=m &&(m-abs(tx)-abs(ty))%2==0)return true;
}
return false;
}
int main()
{
string s;
while(cin>>n){
cin>>s;
cin>>endx>>endy;
memset(x,0,sizeof(x));
memset(y,0,sizeof(y));
for(int i=1;i<=s.length();i++)
{
switch(s[i-1])
{
case 'U':
x[i]=x[i-1];
y[i]=y[i-1]+1;
break;
case 'D':
x[i]=x[i-1];
y[i]=y[i-1]-1;
break;
case 'L':
y[i]=y[i-1];
x[i]=x[i-1]-1;
break;
case 'R':
y[i]=y[i-1];
x[i]=x[i-1]+1;
break;
}
}
//二分 区间长度
int l=0,r=n;
int mid,ans=INF;
while(l<=r){
mid=(l+r)>>1;
if(check(mid)){
r=mid-1;
ans=mid;
}
else
{
l=mid+1;
}
}
if(ans==INF)
{
cout<<"-1"<<endl;
}
else
{
cout<<ans<<endl;
}
}
}