AC通道:http://cogs.pro/cogs/problem/problem.php?pid=2302
【题解】
差分约束,若a比b高,则由a向b连一条权值为1的边,然后用tarjan判环,然后用spfa跑最长路即可。
/*************
cogs 2302
by chty
2016.11.16
*************/
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
#define FILE "reward"
#define MAXN 10010
#define up(i,j,n) for(ll i=j;i<=n;i++)
namespace INIT{
char buf[1<<15],*fs,*ft;
inline char getc() {return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;}
inline ll read(){
ll x=0,f=1; char ch=getc();
while(!isdigit(ch)) {if(ch=='-') f=-1; ch=getc();}
while(isdigit(ch)) {x=x*10+ch-'0'; ch=getc();}
return x*f;
}
}using namespace INIT;
struct node{ll y,next,v;}e[20010];
ll n,m,len,ans,top,bcnt,dfs_clock,q[MAXN],dis[MAXN],vis[MAXN],size[MAXN],stack[MAXN],instack[MAXN],Link[MAXN],in[MAXN],dfn[MAXN],low[MAXN];
void insert(ll x,ll y,ll v) {e[++len].next=Link[x];Link[x]=len;e[len].y=y;e[len].v=v;in[y]++;}
void tarjan(ll x){
dfn[x]=low[x]=++dfs_clock;
stack[++top]=x; instack[x]=1;
for(ll i=Link[x];i;i=e[i].next){
if(!dfn[e[i].y]){
tarjan(e[i].y);
low[x]=min(low[x],low[e[i].y]);
}
else if(instack[e[i].y]) low[x]=min(low[x],dfn[e[i].y]);
}
if(low[x]==dfn[x]){
bcnt++; ll y;
do{
y=stack[top--];
instack[y]=0;
size[bcnt]++;
}while(x!=y);
}
}
void spfa(ll s){
ll head=0,tail=1;
q[1]=s; vis[s]=1; dis[s]=100;
while(++head<=tail){
ll x=q[head];
for(ll i=Link[x];i;i=e[i].next){
if(dis[e[i].y]<dis[x]+e[i].v){
dis[e[i].y]=dis[x]+e[i].v;
if(!vis[e[i].y]){
vis[e[i].y]=1;
q[++tail]=e[i].y;
}
}
}
vis[x]=0;
}
}
int main(){
freopen(FILE".in","r",stdin);
freopen(FILE".out","w",stdout);
n=read(); m=read();
up(i,1,m) {ll x=read(),y=read();insert(y,x,1);}
up(i,1,n) if(!dfn[i]) tarjan(i);
up(i,1,bcnt) if(size[i]>=2) {printf("impossible\n"); return 0;}
memset(dis,-1,sizeof(dis));
up(i,1,n) if(!in[i]) spfa(i);
up(i,1,n) ans+=dis[i];
printf("%lld\n",ans);
return 0;
}