图论练习2

内容:路径计数DP,差分约束              

最短路计数

题目大意

  • 给一个n个点m条边的无向无权图,问从1出发到其他每个点的最短路有多少条
  • 有自环和重边,对答案mod100003

解题思路 

  • 设边权为1,跑最短路
  • \left\{\begin{matrix} if\ dis_v>dis_u+w(u,v) & tot_v=tot_u\\ if \ dis_v=dis_u+w(u,v) &tot_v+=tot_u \end{matrix}\right.
  • tot_u 表示1\rightarrow u的路径数
  • 自环和重边不影响最短路

import java.io.*;
import java.math.BigInteger;
import java.util.PriorityQueue;
import java.util.StringTokenizer;




public class Main{
	static long mod=100003;
	static long inf=Long.MAX_VALUE/2;
	
	static Edge[] e;
	static int[] head;
	static int cnt;
	static
	class Edge{
		int fr,to,nxt;
		long val;
		public Edge(int u,int v,long w) {
			fr=u;
			to=v;
			val=w;
		}
	}
	static void addEdge(int fr,int to,long val) {
		cnt++;
		e[cnt]=new Edge(fr, to, val);
		e[cnt].nxt=head[fr];
		head[fr]=cnt;
	}
	
	static
	class Node{
		int x;
		long dis;
		public Node(int X,long D) {
			x=X;
			dis=D;
		}
	}
	
	public static void main(String[] args) throws IOException{
		AReader input=new AReader();
	    PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
	    int n=input.nextInt();
	    int m=input.nextInt();
	    
	    e=new Edge[m<<1|1];
	    head=new int[n+1];
	    long[] dis=new long[n+1];
	    long[] tot=new long[n+1];
	    boolean[] vis=new boolean[n+1];
	    for(int i=1;i<=m;++i) {
	    	int u=input.nextInt();
	    	int v=input.nextInt();
	    	addEdge(u, v, 1);
	    	addEdge(v, u, 1);
	    }
	    for(int i=1;i<=n;++i)dis[i]=inf;
		PriorityQueue<Node> q=new PriorityQueue<Node>((o1,o2)->{
			if(o1.dis-o2.dis>0)return 1;
			else if(o1.dis-o2.dis<0)return -1;
			else return 0;
		});
		dis[1]=0;tot[1]=1;q.add(new Node(1, 0));
		while(!q.isEmpty()) {
			Node now=q.peek();
			q.poll();
			int x=now.x;
			if(vis[x])continue;
			vis[x]=true;
			long disu=now.dis;
			for(int i=head[x];i>0;i=e[i].nxt) {
				int v=e[i].to;
				long w=e[i].val;
				if(vis[v])continue;
				if(dis[v]>disu+w) {
					dis[v]=disu+w;
					tot[v]=tot[x];
					q.add(new Node(v, dis[v]));
				}else if(dis[v]==disu+w) {
					tot[v]=(tot[x]+tot[v])%mod;
				}
			}
		}
	    for(int i=1;i<=n;++i) {
	    	out.println(tot[i]);
	    }
	    
 	    out.flush();
	    out.close();
	}
	static
	class AReader{
	    BufferedReader bf;
	    StringTokenizer st;
	    BufferedWriter bw;

	    public AReader(){
	        bf=new BufferedReader(new InputStreamReader(System.in));
	        st=new StringTokenizer("");
	        bw=new BufferedWriter(new OutputStreamWriter(System.out));
	    }
	    public String nextLine() throws IOException{
	        return bf.readLine();
	    }
	    public String next() throws IOException{
	        while(!st.hasMoreTokens()){
	            st=new StringTokenizer(bf.readLine());
	        }
	        return st.nextToken();
	    }
	    public char nextChar() throws IOException{
	        //确定下一个token只有一个字符的时候再用
	        return next().charAt(0);
	    }
	    public int nextInt() throws IOException{
	        return Integer.parseInt(next());
	    }
	    public long nextLong() throws IOException{
	        return Long.parseLong(next());
	    }
	    public double nextDouble() throws IOException{
	        return Double.parseDouble(next());
	    }
	    public float nextFloat() throws IOException{
	        return Float.parseFloat(next());
	    }
	    public byte nextByte() throws IOException{
	        return Byte.parseByte(next());
	    }
	    public short nextShort() throws IOException{
	        return Short.parseShort(next());
	    }
	    public BigInteger nextBigInteger() throws IOException{
	        return new BigInteger(next());
	    }
	    public void println() throws IOException {
	        bw.newLine();
	    }
	    public void println(int[] arr) throws IOException{
	        for (int value : arr) {
	            bw.write(value + " ");
	        }
	        println();
	    }
	    public void println(int l, int r, int[] arr) throws IOException{
	        for (int i = l; i <= r; i ++) {
	            bw.write(arr[i] + " ");
	        }
	        println();
	    }
	    public void println(int a) throws IOException{
	        bw.write(String.valueOf(a));
	        bw.newLine();
	    }
	    public void print(int a) throws IOException{
	        bw.write(String.valueOf(a));
	    }
	    public void println(String a) throws IOException{
	        bw.write(a);
	        bw.newLine();
	    }
	    public void print(String a) throws IOException{
	        bw.write(a);
	    }
	    public void println(long a) throws IOException{
	        bw.write(String.valueOf(a));
	        bw.newLine();
	    }
	    public void print(long a) throws IOException{
	        bw.write(String.valueOf(a));
	    }
	    public void println(double a) throws IOException{
	        bw.write(String.valueOf(a));
	        bw.newLine();
	    }
	    public void print(double a) throws IOException{
	        bw.write(String.valueOf(a));
	    }
	    public void print(char a) throws IOException{
	        bw.write(String.valueOf(a));
	    }
	    public void println(char a) throws IOException{
	        bw.write(String.valueOf(a));
	        bw.newLine();
	    }
	}
}

[HAOI2012]ROAD

题目链接

题目大意

  •  n个点m条单向有权边,对每条边求有多少条最短路经过该边
  • 答案取模1000000007

 解题思路

  • 对每个点,求从该点出发到其他点的最短路,将用到的边保留生成新图,其余边无用
  •  对于在新图上的每个点
  • 利用Tuopu求从这个点进入的路径数a,正着累加
  • 利用dfs求从这个点出去的路径数b,倒着累加
  • 对于边u\rightarrow vNum_{u\rightarrow v}+=a_u*b_v\%mod

import java.io.*;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.StringTokenizer;




public class Main{
	
	
	static int n;
	static int m;
	static long inf=Long.MAX_VALUE/2;
	static long mod=1000000007;
	
	static
	class Map{
		public Map() {
			cnt=0;
			head=new int[n+1];
			e=new Edge[m+1];
			dis=new long[n+1];
			vis=new boolean[n+1];
		}
		int cnt;
		int[] head;
		static
		class Edge{
			int fr,to,nxt;
			long val;
			public Edge(int u,int v,long w) {
				fr=u;
				to=v;
				val=w;
			}
		}
		Edge[] e;
		void addEdge(int fr,int to,long val) {
			cnt++;
			e[cnt]=new Edge(fr, to, val);
			e[cnt].nxt=head[fr];
			head[fr]=cnt;
		}
		static
		class Node{
			int x;
			long dis;
			public Node(int X,long D) {
				x=X;
				dis=D;
			}
		}
		long[] dis;
		boolean[] vis;
		void Dij(int s) {
			for(int i=1;i<=n;++i) dis[i]=inf;
			for(int i=1;i<=n;++i) vis[i]=false;
			PriorityQueue<Node> q=new PriorityQueue<Node>((o1,o2)->{
				if(o1.dis-o2.dis>0)return 1;
				else if(o1.dis-o2.dis<0) return -1;
				else return 0;
			});
			dis[s]=0;
			q.add(new Node(s, 0));
			while(!q.isEmpty()) {
				Node now=q.peek();
				q.poll();
				int x=now.x;
				if(vis[x])continue;
				long disu=now.dis;
				vis[x]=true;
				for(int i=head[x];i>0;i=e[i].nxt){
					int v=e[i].to;
					long w=e[i].val;
					if(vis[v])continue;
					if(disu+w<dis[v]) {
						dis[v]=disu+w;
						q.add(new Node(v,dis[v]));
					}
				}
			}
		}
		void Make_Tp() {
			for(int i=1;i<=cnt;++i) {
				int u=e[i].fr;
				int v=e[i].to;
				long w=e[i].val;
				if(dis[u]+w==dis[v]) {
					Tp.addEdge(u, v, w, i);
					Tp.in[v]++;
				}
			}
		}
	}
	static
	class Mapp {
		public Mapp() {
			cnt=0;
			head=new int[n+1];
			e=new Edge[m+1];
			in=new int[n+1];
			a=new long[n+1];
			b=new long[n+1];
		}
		int cnt;
		int[] head;
		static
		class Edge{
			int fr,to,nxt,id;
			long val;
			public Edge(int u,int v,long w) {
				fr=u;
				to=v;
				val=w;
			}
		}
		Edge[] e;
		void addEdge(int fr,int to,long val,int id) {
			cnt++;
			e[cnt]=new Edge(fr, to, val);
			e[cnt].id=id;
			e[cnt].nxt=head[fr];
			head[fr]=cnt;
		}
		
		int[] in;
		//s->i--j<-t
		long[] a;  
		long[] b;
		
		void stoi(int s) {
			Queue<Integer> q=new LinkedList<Integer>();
			q.add(s);
			a[s]=1;
			while(!q.isEmpty()) {
				int u=q.peek();
				q.poll();
				for(int i=head[u];i>0;i=e[i].nxt) {
					int v=e[i].to;
					a[v]=(a[v]+a[u])%mod;
					in[v]--;
					if(in[v]==0)q.add(v);
				}
			}
		}
		void jfrt(int u) {//不用建反图跑拓扑
			if(b[u]!=0)return;
			for(int i=head[u];i>0;i=e[i].nxt) {
				int v=e[i].to;
				jfrt(v);
				b[u]=(b[u]+b[v])%mod;
			}
			b[u]++;//j<-j也算
		}
		void getf() {
			for(int i=1;i<=cnt;++i) {
				int id=e[i].id;
				int u=e[i].fr;
				int v=e[i].to;
				f[id]=(f[id]+a[u]*b[v]%mod)%mod;
			}
		}
		void clear() {
			cnt=0;
			Arrays.fill(head, 0);
			Arrays.fill(in, 0);
			Arrays.fill(a, 0);
			Arrays.fill(b, 0);
		}
	}
	static Map T;
	static Mapp Tp;
	static long[] f;
	static void get(int s) {
		T.Dij(s);
		Tp.clear();
		T.Make_Tp();
		Tp.stoi(s);
		Tp.jfrt(s);
		Tp.getf();
	}
	
	
	public static void main(String[] args) throws IOException{
		AReader input=new AReader();
	    PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
	    n=input.nextInt();
	    m=input.nextInt();
	    T=new Map();
	    Tp=new Mapp();
	    f=new long[m+1];
	    for(int i=1;i<=m;++i) {
	    	int u=input.nextInt();
	    	int v=input.nextInt();
	    	long w=input.nextLong();
	    	T.addEdge(u, v, w);
	    }
	    for(int i=1;i<=n;++i) get(i);
	    
	    for(int i=1;i<=m;++i)out.println(f[i]);
	   
	    
 	    out.flush();
	    out.close();
	}
	static
	class AReader{
	    BufferedReader bf;
	    StringTokenizer st;
	    BufferedWriter bw;

	    public AReader(){
	        bf=new BufferedReader(new InputStreamReader(System.in));
	        st=new StringTokenizer("");
	        bw=new BufferedWriter(new OutputStreamWriter(System.out));
	    }
	    public String nextLine() throws IOException{
	        return bf.readLine();
	    }
	    public String next() throws IOException{
	        while(!st.hasMoreTokens()){
	            st=new StringTokenizer(bf.readLine());
	        }
	        return st.nextToken();
	    }
	    public char nextChar() throws IOException{
	        //确定下一个token只有一个字符的时候再用
	        return next().charAt(0);
	    }
	    public int nextInt() throws IOException{
	        return Integer.parseInt(next());
	    }
	    public long nextLong() throws IOException{
	        return Long.parseLong(next());
	    }
	    public double nextDouble() throws IOException{
	        return Double.parseDouble(next());
	    }
	    public float nextFloat() throws IOException{
	        return Float.parseFloat(next());
	    }
	    public byte nextByte() throws IOException{
	        return Byte.parseByte(next());
	    }
	    public short nextShort() throws IOException{
	        return Short.parseShort(next());
	    }
	    public BigInteger nextBigInteger() throws IOException{
	        return new BigInteger(next());
	    }
	    public void println() throws IOException {
	        bw.newLine();
	    }
	    public void println(int[] arr) throws IOException{
	        for (int value : arr) {
	            bw.write(value + " ");
	        }
	        println();
	    }
	    public void println(int l, int r, int[] arr) throws IOException{
	        for (int i = l; i <= r; i ++) {
	            bw.write(arr[i] + " ");
	        }
	        println();
	    }
	    public void println(int a) throws IOException{
	        bw.write(String.valueOf(a));
	        bw.newLine();
	    }
	    public void print(int a) throws IOException{
	        bw.write(String.valueOf(a));
	    }
	    public void println(String a) throws IOException{
	        bw.write(a);
	        bw.newLine();
	    }
	    public void print(String a) throws IOException{
	        bw.write(a);
	    }
	    public void println(long a) throws IOException{
	        bw.write(String.valueOf(a));
	        bw.newLine();
	    }
	    public void print(long a) throws IOException{
	        bw.write(String.valueOf(a));
	    }
	    public void println(double a) throws IOException{
	        bw.write(String.valueOf(a));
	        bw.newLine();
	    }
	    public void print(double a) throws IOException{
	        bw.write(String.valueOf(a));
	    }
	    public void print(char a) throws IOException{
	        bw.write(String.valueOf(a));
	    }
	    public void println(char a) throws IOException{
	        bw.write(String.valueOf(a));
	        bw.newLine();
	    }
	}
}


逛公园

题目链接

题目大意 

  • 给一个n个点m条边构成的有向带权图,没有自环和重边
  • 1\rightarrow n的最短路长为d,求1\rightarrow n有多少条长度\left [ d,d+k \right ]的路径

解题思路                     

  • 求从1出发的最短路,1\rightarrow u=d_u
  • f[u][x]表示1\rightarrow u=d_u+x,x\leq k,路径个数
  • u\rightarrow v\Rightarrow d_u+x+w(u,v)=d_v+y,y\leq k
  • x=d_v-d_u-w(u,v)+y
  • f[v][y]+=f[u][x]
  • 所以反向建图,dfs(n,y),y\in [0,k]
  • 若最短路上有0环,则会有无穷多路径
  • 若在dfs中,该f[v][y]还在等待递归返回答案时,再次被访问,则有0环
  • 初始dfs(1,0),判断1在不在0环内,在则f[1][0]=\infty,有0环,反之,f[1][0]=1

import java.io.*;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.PriorityQueue;
import java.util.StringTokenizer;
import java.util.Vector;




public class Main{
	static int inf=Integer.MAX_VALUE/2;

	static int md;
	 
	
	static
	class Node{
		int x;
		int dis;
		public Node(int X,int D) {
			x=X;
			dis=D;
		}
	}
	static
	class Edge{
		int fr,to,nxt;
		int val;
		public Edge(int u,int v,int w) {
			fr=u;
			to=v;
			val=w;
		}
	}
	static
	class Map{
		Edge[] e;
		int[] head;
		int cnt;
		public Map(int n,int m) {
			e=new Edge[m<<1|1];
			head=new int[n+1];
			cnt=0;
		}
		void addEdge(int fr,int to,int val) {
			cnt++;
			e[cnt]=new Edge(fr, to, val);
			e[cnt].nxt=head[fr];
			head[fr]=cnt;
		}
	}
	static boolean fail=false;
	static Map T;
	static Map Tp;
	static int[] dis;
	static long[][] f;
	static boolean[][] inqu;
	static void dfs(int v,int k) {
		//disu+x+w(u,v)=disv+k
		//x=disv-disu-w+k
		if(fail)return;
		if(inqu[v][k]) {
			//这个状态还没处理又绕回来了,k不变,即走了0环
			fail=true;
			return;
		}
		
		if(f[v][k]>0)return;
		
		inqu[v][k]=true;
		long res=0;
		for(int i=Tp.head[v];i>0;i=Tp.e[i].nxt) {
			int u=Tp.e[i].to;
			int w=Tp.e[i].val;
			int x=dis[v]-dis[u]-w+k;
			if(x<0)continue;
			dfs(u, x);
			res=(res+f[u][x])%md;
			if(fail)return;
		}
		f[v][k]=res;
		inqu[v][k]=false;
	}
	
	public static void main(String[] args) throws IOException{
		AReader input=new AReader();
	    PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
	    
	    int O=input.nextInt();
	    while(O>0) {
	    	int n=input.nextInt();
		    int m=input.nextInt();
		    int k=input.nextInt();
		    md=input.nextInt();
		    fail=false;
		    T=new Map(n, m);
		    Tp=new Map(n, m);
		    f=new long[n+1][k+1];
		    dis=new int[n+1];
		    inqu=new boolean[n+1][k+1];
		    boolean[] vis=new boolean[n+1];
		    for(int i=1;i<=m;++i) {
		    	int u=input.nextInt();
		    	int v=input.nextInt();
		    	int w=input.nextInt();
		    	T.addEdge(u, v, w);
		    	Tp.addEdge(v, u, w);
		    }
		    for(int i=1;i<=n;++i)dis[i]=inf;
			PriorityQueue<Node> q=new PriorityQueue<Node>((o1,o2)->{
				return o1.dis-o2.dis;
			});
			dis[1]=0;q.add(new Node(1, 0));
			while(!q.isEmpty()) {
				Node now=q.peek();
				q.poll();
				int x=now.x;
				if(vis[x])continue;
				vis[x]=true;
				int disu=now.dis;
				for(int i=T.head[x];i>0;i=T.e[i].nxt) {
					int v=T.e[i].to;
					int w=T.e[i].val;
					if(vis[v])continue;
					if(dis[v]>disu+w) {
						dis[v]=disu+w;
						q.add(new Node(v, dis[v]));
					}
				}
			}

		    long ans=0;
		    dfs(1,0);
		    f[1][0]=1;
		    
		    for(int i=0;i<=k;++i) {
		    	if(fail)break;
		    	dfs(n, i);
		    	ans=(ans+f[n][i])%md;
		    }
		    if(fail)out.println(-1);
		    else out.println(ans);
		    
		    T=null;
		    Tp=null;
		    inqu=null;
		    dis=null;
		    f=null;
	    	O--;
	    }
	    
	    
 	    out.flush();
	    out.close();
	}
	static
	class AReader{
	    BufferedReader bf;
	    StringTokenizer st;
	    BufferedWriter bw;

	    public AReader(){
	        bf=new BufferedReader(new InputStreamReader(System.in));
	        st=new StringTokenizer("");
	        bw=new BufferedWriter(new OutputStreamWriter(System.out));
	    }
	    public String nextLine() throws IOException{
	        return bf.readLine();
	    }
	    public String next() throws IOException{
	        while(!st.hasMoreTokens()){
	            st=new StringTokenizer(bf.readLine());
	        }
	        return st.nextToken();
	    }
	    public char nextChar() throws IOException{
	        //确定下一个token只有一个字符的时候再用
	        return next().charAt(0);
	    }
	    public int nextInt() throws IOException{
	        return Integer.parseInt(next());
	    }
	    public long nextLong() throws IOException{
	        return Long.parseLong(next());
	    }
	    public double nextDouble() throws IOException{
	        return Double.parseDouble(next());
	    }
	    public float nextFloat() throws IOException{
	        return Float.parseFloat(next());
	    }
	    public byte nextByte() throws IOException{
	        return Byte.parseByte(next());
	    }
	    public short nextShort() throws IOException{
	        return Short.parseShort(next());
	    }
	    public BigInteger nextBigInteger() throws IOException{
	        return new BigInteger(next());
	    }
	    public void println() throws IOException {
	        bw.newLine();
	    }
	    public void println(int[] arr) throws IOException{
	        for (int value : arr) {
	            bw.write(value + " ");
	        }
	        println();
	    }
	    public void println(int l, int r, int[] arr) throws IOException{
	        for (int i = l; i <= r; i ++) {
	            bw.write(arr[i] + " ");
	        }
	        println();
	    }
	    public void println(int a) throws IOException{
	        bw.write(String.valueOf(a));
	        bw.newLine();
	    }
	    public void print(int a) throws IOException{
	        bw.write(String.valueOf(a));
	    }
	    public void println(String a) throws IOException{
	        bw.write(a);
	        bw.newLine();
	    }
	    public void print(String a) throws IOException{
	        bw.write(a);
	    }
	    public void println(long a) throws IOException{
	        bw.write(String.valueOf(a));
	        bw.newLine();
	    }
	    public void print(long a) throws IOException{
	        bw.write(String.valueOf(a));
	    }
	    public void println(double a) throws IOException{
	        bw.write(String.valueOf(a));
	        bw.newLine();
	    }
	    public void print(double a) throws IOException{
	        bw.write(String.valueOf(a));
	    }
	    public void print(char a) throws IOException{
	        bw.write(String.valueOf(a));
	    }
	    public void println(char a) throws IOException{
	        bw.write(String.valueOf(a));
	        bw.newLine();
	    }
	}
}

[SCOI2011]糖果

题目链接

题目大意

  • n个人,k对限制
  • 问在满足限制的条件下,每个人至少有一个糖果时,所需的糖果总数 

解题思路 

  • \left\{\begin{matrix} a=b\Rightarrow a\leq b,b\leq a\Rightarrow a\overset{0}{\rightarrow}b,b\overset{0}{\rightarrow}a\\ a\leq b\Rightarrow a\overset{0}{\rightarrow}b\\ a< b\Rightarrow a+1\leq b\Rightarrow a\overset{1}{\rightarrow}b\\ b\leq a\Rightarrow b\overset{0}{\rightarrow}a\\ b< a\Rightarrow b+1\leq a\Rightarrow b\overset{1}{\rightarrow}a \end{matrix}\right.
  • j将限制转化为边建图后,要满足限制,则要跑最长路
  • 将权为1的边转为权为-1,用Spfa跑最短路
  • 若一个点被更新n次,则出现负环,无解
  • 初始dis_i=-1,表示至少有一个糖果 
  • ans-=\sum_{i=1}^{n}dis_i

import java.io.*;
import java.io.ObjectInputStream.GetField;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.StringTokenizer;
import java.util.Vector;



public class Main{
//	static int inf=Integer.MAX_VALUE/2;
	static boolean fail=false;
	static
	class Edge{
		int fr,to,nxt;
		int val;
		public Edge(int u,int v,int w) {
			fr=u;
			to=v;
			val=w;
		}
	}
	static
	class Map{
		Edge[] e;
		int[] head;
		int cnt;
		int vis;
		public Map(int n,int m) {
			e=new Edge[m];
			head=new int[n+1];
			cnt=0;
			vis=0;
		}
		void addEdge(int fr,int to,int val) {
			cnt++;
			e[cnt]=new Edge(fr, to, val);
			e[cnt].nxt=head[fr];
			head[fr]=cnt;
		}
		
		long spfa(int n) {
			boolean[] inqu=new boolean[n+1];
			int[] dis=new int[n+1];
			int[] tot=new int[n+1];
			Queue<Integer> q=new LinkedList<Integer>();
			for(int i=1;i<=n;++i) {
				dis[i]=-1;
				inqu[i]=true;
				q.add(i);
			}
			while(!q.isEmpty()) {
				int u=q.peek();
				q.poll();
				inqu[u]=false;
				
				for(int i=head[u];i>0;i=e[i].nxt) {
					int v=e[i].to;
					int w=e[i].val;
					if(dis[v]>dis[u]+w) {
						dis[v]=dis[u]+w;
						tot[v]++;
						if(tot[v]>=n) {
							fail=true;
							break;
						}
						if(inqu[v])continue;
						inqu[v]=true;
						q.add(v);
					}
				}
				if(fail)break;
			}
			if(fail)return 0;
			long ans=0;
			for(int i=1;i<=n;++i) {
				ans-=dis[i];
			}
			return ans;
		}
	}
	public static void main(String[] args) throws IOException{
		AReader input=new AReader();
	    PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
	    int n=input.nextInt();
	    int m=input.nextInt();
	    Map T=new Map(n, m<<1|1);
	    int[] in=new int[n+1];
	    for(int i=1;i<=m;++i) {
	    	int x=input.nextInt();
	    	int a=input.nextInt();
	    	int b=input.nextInt();
	    	//最短路
	    	if(x==1) {
	    		//a==b=> a<=b,b<=a
	    		T.addEdge(a, b, 0);
	    		T.addEdge(b, a, 0);
	    	}else if(x==2) {
	    		//a<b=>a+1<=b
                if(a==b){
                   out.print("-1");
                    out.flush();
                    out.close();
                    return;
                }
	    		T.addEdge(a, b, -1);
	    	}else if(x==3) {
	    		//a>=b
	    		T.addEdge(b, a, 0);
	    	}else if(x==4) {
	    		//a>b=>b+1<=a
               if(a==b){
                   out.print("-1");
                    out.flush();
                    out.close();
                    return;
                }
	    		T.addEdge(b, a, -1);
	    	}else {
	    		//a<=b
	    		T.addEdge(a, b, 0);
	    	}
	    }
	    long ans=T.spfa(n);
	    if(fail) {
	    	out.print("-1");
	    }else out.print(ans);
 	    out.flush();
	    out.close();
	}
	static
	class AReader{
	    BufferedReader bf;
	    StringTokenizer st;
	    BufferedWriter bw;

	    public AReader(){
	        bf=new BufferedReader(new InputStreamReader(System.in));
	        st=new StringTokenizer("");
	        bw=new BufferedWriter(new OutputStreamWriter(System.out));
	    }
	    public String nextLine() throws IOException{
	        return bf.readLine();
	    }
	    public String next() throws IOException{
	        while(!st.hasMoreTokens()){
	            st=new StringTokenizer(bf.readLine());
	        }
	        return st.nextToken();
	    }
	    public char nextChar() throws IOException{
	        //确定下一个token只有一个字符的时候再用
	        return next().charAt(0);
	    }
	    public int nextInt() throws IOException{
	        return Integer.parseInt(next());
	    }
	    public long nextLong() throws IOException{
	        return Long.parseLong(next());
	    }
	    public double nextDouble() throws IOException{
	        return Double.parseDouble(next());
	    }
	    public float nextFloat() throws IOException{
	        return Float.parseFloat(next());
	    }
	    public byte nextByte() throws IOException{
	        return Byte.parseByte(next());
	    }
	    public short nextShort() throws IOException{
	        return Short.parseShort(next());
	    }
	    public BigInteger nextBigInteger() throws IOException{
	        return new BigInteger(next());
	    }
	    public void println() throws IOException {
	        bw.newLine();
	    }
	    public void println(int[] arr) throws IOException{
	        for (int value : arr) {
	            bw.write(value + " ");
	        }
	        println();
	    }
	    public void println(int l, int r, int[] arr) throws IOException{
	        for (int i = l; i <= r; i ++) {
	            bw.write(arr[i] + " ");
	        }
	        println();
	    }
	    public void println(int a) throws IOException{
	        bw.write(String.valueOf(a));
	        bw.newLine();
	    }
	    public void print(int a) throws IOException{
	        bw.write(String.valueOf(a));
	    }
	    public void println(String a) throws IOException{
	        bw.write(a);
	        bw.newLine();
	    }
	    public void print(String a) throws IOException{
	        bw.write(a);
	    }
	    public void println(long a) throws IOException{
	        bw.write(String.valueOf(a));
	        bw.newLine();
	    }
	    public void print(long a) throws IOException{
	        bw.write(String.valueOf(a));
	    }
	    public void println(double a) throws IOException{
	        bw.write(String.valueOf(a));
	        bw.newLine();
	    }
	    public void print(double a) throws IOException{
	        bw.write(String.valueOf(a));
	    }
	    public void print(char a) throws IOException{
	        bw.write(String.valueOf(a));
	    }
	    public void println(char a) throws IOException{
	        bw.write(String.valueOf(a));
	        bw.newLine();
	    }
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/370751.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于OpenCV灰度图像转GCode的双向扫描实现

基于OpenCV灰度图像转GCode的双向扫描实现 引言激光雕刻简介OpenCV简介实现步骤 1.导入必要的库2. 读取灰度图像3. 图像预处理4. 生成GCode 1. 简化版的双向扫描2. 优化版的双向扫描 5. 保存生成的GCode6. 灰度图像双向扫描代码示例 总结 系列文章 ⭐深入理解G0和G1指令&…

【深入浅出Java性能调优】「底层技术原理体系」详细分析探索Java服务器性能监控Metrics框架的实现原理分析(Dropwizard度量基础案例指南)

深入探索Java服务器性能监控Metrics框架的实现原理分析 前提介绍Dropwizard MetricsDropwizard的特点Dropwizard的开发案例需要引入Maven依赖常用度量类型Meter(每秒请求数为单位测量请求率)定义度量核心MetricRegistry构建对应的Meter指标对象请求标记采样业务方法控制报告器…

利用Excel爬取网页数据

想要获取网页上的表格数据&#xff0c;可以通过Excel自带的功能&#xff0c;从网站导入数据&#xff0c;并且可以实时刷新最新数据。具体步骤如下&#xff1a; 1、新建Excel&#xff0c;打开&#xff0c;选择【数据】-【自网站】 2、在弹出的对话框中输入目标网址&#xff0c;…

Java常用

文章目录 基础基础数据类型内部类Java IOIO多路复用重要概念 Channel **通道**重要概念 Buffer **数据缓存区**重要概念 Selector **选择器** 关键字final 元注解常用接口异常处理ErrorException JVM与虚拟机JVM内存模型本地方法栈虚拟机栈 Stack堆 Heap方法区 Method Area (JD…

JavaSE-项目小结-IP归属地查询(本地IP地址库)

一、项目介绍 1. 背景 IP地址是网络通信中的重要标识&#xff0c;通过分析IP地址的归属地信息&#xff0c;可以帮助我们了解访问来源、用户行为和网络安全等关键信息。例如应用于网站访问日志分析&#xff1a;通过分析访问日志中的IP地址&#xff0c;了解网站访问者的地理位置分…

毫米波雷达在汽车领域的原理、优势和未来趋势

1 毫米波雷达的原理 汽车引入毫米波雷达最初主要是为了实现盲点监测和定距巡航。毫米波实质上是电磁波&#xff0c;其频段位于无线电和可见光、红外线之间&#xff0c;频率范围为10GHz-200GHz。工作原理类似一般雷达&#xff0c;通过发射无线电波并接收回波&#xff0c;利用障…

vscode 无法远程连接waiting the server log

使用版本 报错信息 相关日志 [17:32:59.765] > Waiting for server log... [17:32:59.801] > Waiting for server log... [17:32:59.831] > > * > * Visual Studio Code Server > * > * By using the software, you agree to > * the Visual Studio…

Github开源项目Excalidraw:简洁易用的手绘风格白板工具

Excalidraw是Github上的一个开源项目&#xff0c;它提供了一个简洁易用的手绘图形创建工具&#xff0c;用户可以通过它创建流程图、示意图、架构图和其他各种图形。本文将介绍Excalidraw的特点和功能&#xff0c;并探讨其在技术层面上的优势和扩展能力。 GitHub地址&#xff1a…

Mysql学习记录补充

索引 在无索引情况下&#xff0c;就需要从第一行开始扫描&#xff0c;一直扫描到最后一行&#xff0c;我们称之为 全表扫描&#xff0c;性能很低。 如果我们针对于这张表建立了索引&#xff0c;假设索引结构就是二叉树&#xff0c;那么也就意味着&#xff0c;会对age这个字段…

【数据结构与算法】(8)基础数据结构 之 优先级队列的无序数组实现、有序数组实现、堆实现详细代码示例讲解

目录 2.7 优先级队列1) 无序数组实现2) 有序数组实现3) 堆实现习题E01. 合并多个有序链表-Leetcode 23 2.7 优先级队列 1) 无序数组实现 要点 入队保持顺序出队前找到优先级最高的出队&#xff0c;相当于一次选择排序 public class PriorityQueue1<E extends Priority&g…

Amazon Bedrock ——使用Prompt构建AI软文撰写师的生成式人工智能应用程序

Amazon Bedrock 是一项完全托管的服务&#xff0c;通过单个 API 提供来自 AI21 Labs、Anthropic、Cohere、Meta、Stability AI 和 Amazon 等领先人工智能公司的高性能基础模型&#xff08;FM&#xff09;&#xff0c;以及通过安全性、隐私性和负责任的 AI 构建生成式人工智能应…

QCustomplot实现灰度曲线图

从 QCustomplot官网 https://www.qcustomplot.com/index.php/download 下载支持文件。首页有些demo可以进行参考学习。 新建一个Qt工程&#xff0c;将下载得到的qcustomplot.h和qcustomplot.cpp文件加入到当前工程。pro文件中加上 printsupport 在ui界面中&#xff0c;添加一…

【算法与数据结构】739、LeetCode每日温度

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;   程序如下&#xff1a; 复杂度分析&#xff1a; 时间复杂度&#xff1a; O ( ) O() O()。空间复…

CocosCreator3.8源码分析

Cocos Creator架构 Cocos Creator 拥有两套引擎内核&#xff0c;C 内核 和 TypeScript 内核。C 内核用于原生平台&#xff0c;TypeScript 内核用于 Web 和小游戏平台。 在引擎内核之上&#xff0c;是用 TypeScript 编写的引擎框架层&#xff0c;用以统一两套内核的差异&#xf…

12. onnx转为rknn测试时有很多重叠框的修改(python)

我们下载rknn-toolkit2-master后并进行前面的处理后&#xff0c;进入到rknn-toolkit2-master\examples\onnx\yolov5文件夹&#xff0c;里面有个test.py文件&#xff0c;打开该文件&#xff0c;其代码如下&#xff1a; # -*- coding: utf-8 -*- # coding:utf-8import os import…

Photoshop CS6 下载安装教程,保姆级教程,小白也能轻松搞的,附安装包

前言 Adobe Photoshop CS6强大的照片拍摄和突破性的新功能&#xff0c;用于复杂的图形、选择、逼真的绘画和装饰智能。创建惊人的高动态范围(HDR)图像。用逼真的笔触和混合的颜色绘画。消除噪音&#xff0c;添加种子&#xff0c;并绘制一个国家最先进的摄影设备的草图。凭借原…

多播路由选择

目录 1 多播路由选择 1.1 转发多播数据报时使用三种方法 (1) 洪泛与剪除 RPB 的要点&#xff1a; 1.检查&#xff0c;转发 2.形成以源为根节点的多播转发树 3.剪枝与嫁接 (2) 隧道技术 (tunneling) (3) 基于核心的发现技术 1.2 几种多播路由选择协议 1 多播路由选择 …

挑战杯 python 爬虫与协同过滤的新闻推荐系统

1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; python 爬虫与协同过滤的新闻推荐系统 &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1a;3分工作量&#xff1a;3分创新点&#xff1a;4分 该项目较为新颖&…

算法42:天际线问题(力扣218题)---线段树

218. 天际线问题 城市的 天际线 是从远处观看该城市中所有建筑物形成的轮廓的外部轮廓。给你所有建筑物的位置和高度&#xff0c;请返回 由这些建筑物形成的 天际线 。 每个建筑物的几何信息由数组 buildings 表示&#xff0c;其中三元组 buildings[i] [lefti, righti, heig…

#RAG|NLP|Jieba|PDF2WORD# pdf转word-换行问题

文档在生成PDF时,文宁都发生了什么。本文讲解了配置对象、resources对象和content对象的作用,以及字体、宇号、坐标、文本摆放等过程。同时,还解释了为什么PDF转word或转文字都是一行一行的以及为什么页眉页脚的问题会加大识别难度。最后提到了文本的编码和PDF中缺少文档结构标…