图论练习2

news2024/11/15 23:43:20

内容:路径计数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();
	    }
	}
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Blender教程(基础)-面的切割-10

快捷键K切割&#xff0c;菜单选项切割. 一、随意切割 物体在编辑模式下&#xff0c;按键盘K建切割物体。 二、中点切割 先按K键&#xff0c;再按shift键&#xff0c;会自动吸附到每条边的中点进行切割。 三、取消吸附 切割时会自动吸附到顶点或边 关闭快速吸附 按K键再按…

山东淄博刑侦大队利用无人机抓获盗窃团伙

山东淄博刑侦大队利用无人机抓获盗窃团伙 近期&#xff0c;山东淄博临淄区发生多起盗窃案件。通过视频追踪和调查访问&#xff0c;推断临淄区某村可能为嫌疑人藏匿地点。刑侦大队无人机应急小组迅速到达现场&#xff0c;经无人机高空侦查&#xff0c;发现并锁定了嫌疑人的藏匿…

PHP入门指南:API

PHP入门指南&#xff1a;API 1. 简介2. API的基础概念2.1 什么是API&#xff1f;2.2 API的类型2.3 API的作用2.4 RESTful API2.5 API的基本构成元素 3. PHP与API的交互基础3.1 发送HTTP请求3.2 处理HTTP响应3.3 异常处理3.4 确保安全性 4. 如何在PHP中创建一个简单的API4.1 设计…

【数据分享】1929-2023年全球站点的逐月降雪深度数据(Shp\Excel\免费获取)

气象数据是在各项研究中都经常使用的数据&#xff0c;气象指标包括气温、风速、降水、能见度等指标&#xff0c;说到气象数据&#xff0c;最详细的气象数据是具体到气象监测站点的数据&#xff01; 之前我们分享过1929-2023年全球气象站点的逐月平均气温数据、逐月最高气温数据…

笔记---容斥原理

AcWing,890.能被整除的数 给定一个整数 n n n 和 m m m 个不同的质数 p 1 , p 2 , … , p m p_{1},p_{2},…,p_{m} p1​,p2​,…,pm​。 请你求出 1 ∼ n 1∼n 1∼n 中能被 p 1 , p 2 , … , p m p_{1},p_{2},…,p_{m} p1​,p2​,…,pm​ 中的至少一个数整除的整数有多少…

起心动念 | 生成式 AI 开发实践系列的开端

生成式 AI 和大模型的技术变革力量&#xff0c;正在逐渐影响着我们当下这个时代&#xff0c;全球各行各业都呈现百舸争流、万象更新的趋势。在 2023 年&#xff0c;我们通过各种面向开发者的活动&#xff0c;收集到了大量开发者关于基于生成式 AI 的开发内容需求和建议反馈。开…

免费CRM管理系统哪家好?如何选择?

免费的CRM系统有很多&#xff0c;以下是一些比较常见的&#xff1a;一、Zoho CRM&#xff1b;二、HubSpot CRM&#xff1b;三、Bitrix24&#xff1b;四、SuiteCRM&#xff1b;五、Agile CRM&#xff1b;六、Capsule CRM&#xff1b;七、Insightly。免费的CRM系统虽然功能相对较…

爬虫-网络空间微博信息管理系统的设计与实现-计算机毕业设计源码85633

摘 要 本论文主要论述了如何使用django框架开发一个网络空间微博管理信息系统&#xff0c;本系统将严格按照软件开发流程进行各个阶段的工作&#xff0c;面向对象编程思想进行项目开发。在引言中&#xff0c;作者将论述该系统的当前背景以及系统开发的目的&#xff0c;后续章节…

(每日持续更新)jdk api之ObjectInput基础、应用、实战

博主18年的互联网软件开发经验&#xff0c;从一名程序员小白逐步成为了一名架构师&#xff0c;我想通过平台将经验分享给大家&#xff0c;因此博主每天会在各个大牛网站点赞量超高的博客等寻找该技术栈的资料结合自己的经验&#xff0c;晚上进行用心精简、整理、总结、定稿&…

11. Threejs案例-绘制网格状圆环扭结

11. Threejs案例-绘制网格状圆环扭结 实现效果 知识点 TorusKnotGeometry (圆环缓冲扭结几何体) 创建一个圆环扭结&#xff0c;其特殊形状由一对互质的整数&#xff0c;p 和 q 所定义。如果 p 和 q 不互质&#xff0c;创建出来的几何体将是一个环面链接。 构造器 TorusKno…

解锁MyBatis Plus的强大功能:学习高级操作与DML技巧!

MyBatisPlus 1&#xff0c;DML编程控制1.1 id生成策略控制知识点1&#xff1a;TableId1.1.1 环境构建1.1.2 代码演示AUTO策略步骤1:设置生成策略为AUTO步骤3:运行新增方法 INPUT策略步骤1:设置生成策略为INPUT步骤2:添加数据手动设置ID步骤3:运行新增方法 ASSIGN_ID策略步骤1:设…

12种算法优化CNN-BiLSTM-Attention多特征输入单步预测,机器学习预测全家桶,持续更新,MATLAB代码...

截止到本期&#xff0c;一共发了12篇关于机器学习预测全家桶MATLAB代码的文章。参考文章如下&#xff1a; 1.五花八门的机器学习预测&#xff1f;一篇搞定不行吗&#xff1f; 2.机器学习预测全家桶&#xff0c;多步预测之BiGRU、BiLSTM、GRU、LSTM&#xff0c;LSSVM、TCN、CNN&…

leetcode正则表达式匹配问题(困难)

1.题目描述 2.解题思路&#xff0c;这道题自己没做出来&#xff0c;看了官方的题解&#xff0c;感觉对自己来说确实是比较难想的。使用了动态规划的解决方案&#xff0c;这种方案看题解都不一定能看明白&#xff0c;不过有个评论画图讲解的非常明白。其实仔细看题解的话&#…

Vue服务端渲染

Vue服务端渲染 一、服务端渲染基础 1、概述 我们现在可以使用Vue,React等开发SPA单页面应用&#xff0c;单页面应用的优点&#xff0c;用户体验好&#xff0c;开发效率高&#xff0c;可维护性好等。 缺点&#xff1a;首屏渲染时间长&#xff08;在客户端通过JS来生成html来…

ios搭建OpenGL环境

前言 本篇文章介绍在ios搭建OpenGL开发环境 在app的启动文章中&#xff0c;讲述了一个ios应用是如何启动的以及在IOS 13之后苹果公司推出的多窗口功能&#xff0c;通过app的启动这篇文章&#xff0c;我们基本能随心所欲的搭建一个app应用环境&#xff0c;搭建完成后的基本文件…

Vim工具使用全攻略:从入门到精通

引言 在软件开发的世界里&#xff0c;Vim不仅仅是一个文本编辑器&#xff0c;它是一个让你的编程效率倍增的神器。然而&#xff0c;对于新手来说&#xff0c;Vim的学习曲线似乎有些陡峭。本文将手把手教你如何从Vim的新手逐渐变为高手&#xff0c;深入理解Vim的操作模式&#…

高级编程 (1)

Linux软件编程: 1.Linux: 操作系统的内核 1.管理CPU 2.管理内存 3.管理硬件设备 4.管理文件系统 5.任务调度 2.Shell: 1.保护Linux内核(用户和Linux内核不直接操作,通过操作Shell,Shell和内核交互) 2.命令解释器 3.Shell命令: …

快速理解复杂系统组成学习内容整合

目录 一、复杂系统组成 二、接入系统 (Access System) 三、应用系统 (Application System) 四、基础平台 (Foundation Platform) 五、中间件 (Abundant External Middleware) 六、支撑系统 (Supporting System) 参考文章 一、复杂系统组成 复杂系统是由多个相互关联、相…

【c++】vector用法详解

vector用法详解 vector定义vector容器的构造函数vector容器内元素的访问1.通过下标 [ ]来访问2.通过迭代器来访问3.通过范围for来访问 vector常用函数的用法解析1.size()2.clear()3.capacity()4.reserve()5.resize()6.shrink_to_fit()7.pop_back()8.push_back()9.erase()10.in…

TQ15EG开发板教程:使用vivado2023.1建立hello world工程

1:打开软件建立工程 2:使用vivado创建设计模块并生成bit文件 3:导出硬件平台&#xff0c;使用vitis建立工程 4:使用vitis创建应用程序项目 5:硬件设置与调试 1:打开软件建立工程 打开VIVADO2023.1 创建一个新的工程 输入项目名称和地址&#xff0c;下面那个选项为是否…