oj1638

Posted Lazer

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了oj1638相关的知识,希望对你有一定的参考价值。

分数规划,将边权改造;

第一次被卡精度,mmp

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define maxx 1000000000
#define ecp 1e-5
using namespace std;
struct {int y,next,hh;double flow;}e[10000];
int lin[10000],len=0,re[10000];
int f=0;
int hh[10000];
int read()
{
	int k;cin>>k;return k;
}
void init(int x,int y,double fo,int id)
{
   e[++len].next=lin[x];e[len].y=y;e[len].flow=fo;lin[x]=len,re[len]=len+1;e[len].hh=id;
   e[++len].next=lin[y];e[len].y=x;e[len].flow=fo;lin[y]=len;re[len]=len-1;e[len].hh=id;
   return ;
}
struct pp{int a,b;}sum[10000];
bool aaa(pp q,pp w)
{return q.a>w.a||q.a==w.a&&q.b<w.b;}
int st,n,ed,m;
double zxc,xxx;
int topx=0;
int tot;
int ans[100000];
int top=0;
int a[100000],b[100000],c[100000];
int k[100000];
int  rx1[10000],rx2[10000];
double rv1[10000],rv2[10000];
int q[100000],tail=0,head,level[1000];
bool makelevel()
{
   memset(level,-1,sizeof(level));
   head=0;tail=1;
   q[1]=st;level[st]=1;
   while(head++<tail)
   {
      int x=q[head];
      for(int i=lin[x];i;i=e[i].next)
      {
		 if(k[i]==1)continue;
		 int y=e[i].y;
		 if(e[i].flow>0&&level[y]==-1){level[y]=level[x]+1;q[++tail]=y;}
      }
   }
   return level[ed]!=-1;
}
double makeflow(int x,double flow)
{
   if(x==ed)return flow;
   double axx=0,d=0;
   for(int i=lin[x];i&&axx<flow;i=e[i].next)
   {
		int y=e[i].y;
		if(k[i]==1)continue;
		if(level[y]==level[x]+1&&e[i].flow>0)
		{
			if(d=makeflow(y,min(flow-axx,e[i].flow)))
			{
				axx+=d;
				e[i].flow-=d;
				e[re[i]].flow+=d;
			}
		}
   }
   if(axx==0)level[x]=-1;
   return axx;
}
double dinic()
{
   double ans=0;
   double d;
   while(makelevel())
      while(d=makeflow(st,maxx))
	 ans+=d;
   return ans;
}
double build(double k)
{
   double ansx=0;
   len=0;
   memset(re,0,sizeof(re));
   memset(lin,0,sizeof(lin));
   memset(e,0,sizeof(e));
   for(int i=1;i<=m;i++)
   {
	double fo=1.0*c[i]-k;
	if(fo<0){ansx+=fo;if(f==1){ans[++top]=i;}}
	else {init(a[i],b[i],fo,i);}
   }
   return ansx;
}
void work1()
{
   double left=0,right=1e10;
   double mid;
   while(left+1e-9<right)
    {
		mid=(left+right)/2;
		double g=build(mid);
		g+=dinic();
		if(g>0)left=mid;
		else right=mid;
    }
   zxc=left;
   return ;
}
void rebuild()
{
	for(int i=1;i<=len;i+=2)e[i].flow=e[re[i]].flow=1.0*(e[re[i]].flow+e[i].flow)/2;
}
void work2()
{
	f=1;
	build(zxc);
	xxx=dinic();
	rebuild();
	double j=dinic();
	for(int i=1;i<=len;i++)
    {
		sum[i].a=e[i].flow;
		sum[i].b=i;
    }
   sort(sum+1,sum+len+1,aaa);
   for(int i=1;i<=len;i++)
   {
	   rebuild();
	   int t=sum[i].b;
	   if(k[t]==1)continue;
	   k[t]=1;
	   k[re[t]]=1;
	   double w=dinic()+e[t].flow;
	   if(w+ecp>=xxx&&w-ecp<=xxx){xxx-=e[t].flow;ans[++top]=e[t].hh;}
	   else k[t]=0,k[re[t]]=0;
   }
   printf("%d\n",top);
   sort(ans+1,ans+top+1);
   for(int i=1;i<=top;i++)
   {
		cout<<ans[i]<<‘ ‘;
   }
   cout<<endl;
   return ;
}
void initx()
{
   n=read();m=read();
   st=1;ed=n;
   for(int i=1;i<=m;i++)
	{a[i]=read();b[i]=read();c[i]=read();}
   return ;
}
int main()
{   
   initx();
   work1();
   work2();
   return 0;
}

  

以上是关于oj1638的主要内容,如果未能解决你的问题,请参考以下文章

Luogu1638逛画展

51单片机驱动TM1638芯片+Proteus仿真

51单片机+TM1638+DS3232驱动数码管按键切换显示时间和日期

九度oj 题目1397:查找数段

51单片机 3个IO口 + TM1638+24个独立按键扫描(非自锁按键)+驱动8位共阳数码管显示+Proteus仿真

TM1638芯片的显存地址详细解读