BZOJ:1001狼抓兔子

简直了非常迷 看到题目毫不犹豫的写了一个网络流,然后果真就TLE了

翻了一下题解,就是最大流最小割定理然后,然后将平面图变成对偶图,相当于是从起点到终点跑一个最短路就可以了 

 神马居然还有这种操作??!

 呃加边那个位置是挺复杂的,但是我写对了呀~

还有一个非常迷的地方就是非要用结构体来存边吗我怎么一用数组就WA啊这是什么歪理是不是BZOJ的评测机有bug 

 至今不知道为什么邻接表会写挂完蛋没救了

#include<cstdio> 
#include<iostream> 
#include<queue> 
#include<algorithm> 
#include<cmath> 
#include<cstring> 
#include<cstdlib> 
using namespace std; 
const int inf=0x3f3f3f3f; 
int n,m; 
int head[2000000+20]; 
int dis[2000000+20]; 
int inq[2000000+20],next[2000000],to[6000000+20]; 
struct node 
     int v,w; 
}e[6000000+20]; 
int k; 
int S,T; 
inline int RD()
{
     char ch;
     int res=0;
     ch= getchar ();
     while (ch< '0' ||ch> '9' )ch= getchar ();
     res=ch- '0' ;
     while ((ch= getchar ())>= '0' &&ch<= '9' )res=res*10+ch- '0' ;
     return res;
}
void addedge( int u, int v, int w) 
{
     next[++k]=head[u];
     e[k].v=v; 
     to[k]=e[k].v;
     e[k].w=w; 
     head[u]=k;
         
     next[++k]=head[v];
     e[k].v=u; 
     to[k]=e[k].v;
     e[k].w=w; 
     head[v]=k; 
void spfa() 
     memset (dis,inf, sizeof (dis)); 
     memset (inq,0, sizeof (inq)); 
     queue< int >q; 
     dis[S]=0; 
     inq[S]=1; 
     q.push(S); 
     while (!q.empty()) 
    
         int now=q.front(); 
         q.pop(); 
         inq[now]=0; 
         for ( int i=head[now];i!=-1;i=next[i]) 
        
             int v=to[i];
             v=e[i].v; 
             if (dis[now]+e[i].w<dis[v]) 
            
                 dis[v]=dis[now]+e[i].w; 
                 if (!inq[v]) 
                
                     inq[v]=1; 
                     q.push(v); 
                
            
        
    
     printf ( "%d\n" ,dis[T]); 
int main() 
     memset (head,-1, sizeof (head));
     memset (to,0, sizeof (to)); 
     k=0; 
     scanf ( "%d%d" ,&n,&m); 
     if (n == 1 || m == 1) 
    
         if (n > m) swap(n, m); 
         int ans = inf; 
         for ( int i = 1; i < m; ++i) 
        
             int x; 
             scanf ( "%d" ,&x); 
             if (x < ans) ans = x; 
        
         printf ( "%d\n" , ans); 
         exit (0); 
    
     S=0,T=2*(m-1)*(n-1)+1; 
     int w; 
     for ( int i=1;i<=n;i++)
       for ( int j=1;j<m;j++)
        if (i==1) addedge(j*2,0,RD());
         else if (i==n)addedge(T,2*((i-2)*(m-1)+j)-1,RD());
              else addedge(2*((i-2)*(m-1)+j)-1,2*((i-1)*(m-1)+j),RD());
          
     for ( int i=1;i<n;i++)
       for ( int j=1;j<=m;j++)
         if (j==1)addedge(2*((i-1)*(m-1)+j)-1,T,RD());
         else if (j==m)addedge(2*((i-1)*(m-1)+j)-2,0,RD());
         else addedge(2*((i-1)*(m-1)+j)-1,2*((i-1)*(m-1)+j)-2,RD());
          
     for ( int i=1;i<n;i++)
       for ( int j=1;j<m;j++)
         addedge(2*((i-1)*(m-1)+j)-1,2*((i-1)*(m-1)+j),RD());
           
     spfa();  
     return 0; 

 

转载于:https://www.cnblogs.com/OcahIBye/p/6805075.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值